Redis 最常見的問題


Redis 常用的五種數據結構

字符串 String

  • 概念:字符串主要用於管理 Redis 字符串值。
  • 容量:最大為數據長度是 512M

列表 List

  • 概念:列表是簡單的字符串列表,按照插入順序排序,可以從列表的頭部或尾部插入一個元素。
  • 容量:一個列表最多可以包含 2^32 - 1 個元素 (4294967295, 每個列表超過40億個元素)。

集合 Set

  • 概念:集合是 String 的無序集合,集合元素是唯一的。
  • 容量:集合中最大可存儲的元素數量為 2^32 - 1 (40 多億)。

哈希 Hash

  • 概念:哈希是一個 String 類型的 field 和 value 的映射表,適合存儲對象。
  • 容量:每個 Hash 可以存儲 2^32 - 1 鍵值對 (40 多億)。

有序集合 Sorted Set

  • 概念:有序集合也是 String 的集合,但每個元素會關聯一個 double 類型的分數 (score) 且集合中的元素是從小到大排序的。
  • 容量:有序集合中最大可存儲的元素數量為 2^32 - 1 (40 多億)。

Redis 常見問題

說一說 Redis 哈希槽的概念 ?

Redis 集群沒有使用一致性 hash,而是引入了哈希槽的概念。
Redis 集群中有 16384 個哈希槽,每個 key 通過 CRC16 校驗后對 16384 取模來決定存儲在那個槽。
集群的每個節點負責一部分 hash 槽。

Redis 為什么選擇單線程?

  • 多線程會頻繁切換上下文消耗大量的 CPU。
  • 單線程支持原子操作,不會存在鎖競爭問題。

為什么不使用 Redis 的事務?

  • 不支持回滾操作,不能滿足原子性。

Redis 集群的利弊

好處

  • 容量增加,處理能力增強。
  • 可按需擴容與縮容。

問題

1、存儲數據時如何選擇節點、查詢數據時如何選擇節點 ?
2、新增節點時如何拉取數據、剔除節點時如何轉移數據 ?

解決方式

為了解決數據與節點直接的映射關系,Redis 引入了槽。
引入槽之后,節點上放置的是槽,槽當中存儲的是數據。

一個集群只能有 16384 個槽,編號為 0 - 16383。這些槽會分配給集群中的所有主節點,分配策略無要求。
可以指定哪些編號的槽分配到哪一個主節點。集群會記錄節點和槽的對應關系。

如何計算 Key 在那個槽?
對 Key 求哈希值,然后對 16384 取余,余數的值就是 Key 對應的槽的編號。
即:CRC16 (Key) % 16384

Redis 為什么需要管道技術?

Redis 提供了一種管道技術,可以讓客戶端一次發送多條命令。
期間不需要等待服務器端的響應,等所有的命令發送完成后,再依次響應。
這樣節省了時間,提升了效率。

Redis 分布式鎖是什么 ?

  • 先拿 setnx 來爭搶鎖,搶到之后,再用 expire 給鎖加一個過期時間防止鎖忘記了釋放。
  • 如果在 setnx 之后,執行 expire 之前進程意外 crash 或重啟維護, 那么就需要把 setnxexpire 合成一條指令來用。

假如 Redis 里面有一億個 key,其中 10 萬個 key 是以某個固定的已知前綴開頭的,如何將它們全部找出來?

  • 使用keys指令可以掃出指定模式的key列表。
  • 如果這個redis正在給線上的業務提供服務,那么使用key指令會導致線程阻塞。(redis是單線程的,執行key指令期間,線上服務會卡頓,直到指令執行完成,服務才會恢復)。在這種場景下,就可以使用scan指令,該指令可以無阻塞的提取出指定模式的key列表,但是會有一定重復的概率,可以在客戶端做一次去重就好了, 但是整體花費的時間會比直接使用keys指令長。

如何實現 Redis 異步隊列 ?

使用 list 結構作為隊列,rpush 生產消息,lpop 消費消息。
lpop 沒有消息的時候,要適當 sleep 一會再重試。
如果不用 sleep, 還有個指令 blpop, 在沒有消息的時候, 他會阻塞住直到有消息。

如果要生產一次消費多次,則需要使用 pub/sub 主題訂閱者模式,可以實現 1:N 的消息隊列。
在消費者下線的情況下,生產的消息會丟失。

在這種情況下,就得使用更專業的消息隊列,例如 RabbitMQ。

如何實現 Redis 延時隊列 ?

使用 SortedSet,拿時間戳作為 Score, 消息內容作為 key 調用 zadd 來生產消息,
消費者用 zrangebysocre 指令獲取N秒之前的數據輪詢進行處理。

如果有大量的 key 需要設置統一時間過期,需要注意什么 ?

如果有大量的 key 過期時間設置過於集中,到過期的那個時間點。
redis 可能會出現短暫的卡頓現象。一般需要在時間生加上一個隨機值, 使得過期時間分散一些。

Redis 如何做持久化 ?

bgsave 做鏡像全量持久化, aof 做增量持久化。
因為 bgsave 會耗費較長時間, 不夠實時, 在停機的時候會導致大量丟失數據, 所以aof來配合使用。
redis 實例重啟時, 會使用 bgsave 持久化文件重新構建內存, 在使用 aof 重放近期的操作指令來實現完整恢復重啟之前的狀態。

如果不要求性能, 在每條寫指令是都 sync 一下磁盤, 就不會丟失數據。
但是在高性能的要求下每次都 sync 是不現實的, 一般都使用定時 sync, 比如1s1次, 這個時候最大就會丟失1s的數據。

bgsave 的原理是, forkcowfork 是指 redis 通過創建子進程來進行 bgsave操作。
cow 指的是 copy on write, 子進程創建后, 父進程通過共享數據段。
父進程繼續提供讀寫服務, 寫臟的頁面數據會逐漸和子進程分離開來。

Pipeline 有什么好處?

可以將多次 IO 往返的時間縮減為一次, 前提是 pipeline 執行的指令質檢沒有因果相關性。
使用 redis-benchmark 進行壓測的時候可以發現影響 redisQPS 峰值的一個重要因素是 piepline 批次指令的數目。

Redis 的同步機制是如何操作的?

redis 可以使用主從同步, 從從同步。
第一次同步時, 主節點做一次 bgsave, 並同時將后續修改操作記錄到內存buffer。
待完成后將 rdb 文件全量同步到復制節點, 復制節點接受完成后, 將rdb鏡像加載到內存。
加載完成后, 再通知主節點將修改期間的操作 記錄同步到復制節點進行重放就完成了同步過程。

Redis 集群的原理?

redis sentinal 着眼於高可用, 在 master 宕機時會自動將 slave 提升為 master, 繼續提供服務。

redis cluster 着眼於擴展性, 在單個 redis 內存不足時, 使用 cluster 進行分片存儲。

緩存穿透

現象

查詢不存在的數據,緩存中沒有數據,數據庫也沒有數據。
因此所有的請求都訪問到了數據庫,給數據庫造成了壓力。

解決方法

1、采用布隆過濾器,將所有可能存在的數據,哈希到一個很大的 bitmap 中,
一個一定不存在的數據會被 bitmap 攔截調,從而避免了對數據庫的查詢壓力。

2、如果查詢的數據為空,那么直接將空數據也緩存起來並設置較短的過期時間。
這樣下次訪問的時候,就直接返回空值。

緩存預熱

系統上線之后,將需要緩存的數據直接加載到內存。

實現思路:

1、直接寫個緩存刷新命令,上線時手動操作。
2、項目啟動時自動加載緩存到內存。
3、定時刷新緩存。

Redis 的三種刪除策略

定時刪除

在設置鍵的過期時間的同時,創建一個定時任務。當鍵達到過期時間時,立即執行對鍵的刪除操作。

  • 優點

對內存友好,定時刪除策略可以保證過期鍵會盡可能的快被刪除,並且釋放過期鍵所占用的內存。

  • 缺點

對 CPU 時間片不友好,在過期鍵比較多的情況下。刪除任務會占用很大一部分 CPU 時間片,在內存不緊張但是 CPU 時間緊張時.將 CPU 事件用在刪除和當前任務無關的過期鍵上,會影響服務器的響應時間和吞吐量。

惰性刪除

  • 優點

對 cpu 時間友好,在每次從鍵空間獲取鍵時進行過期鍵檢查並是否刪除,刪除目標也僅限當前處理的鍵,這個策略不會在其他無關的刪除任務上花費任何 cpu 時間。

  • 缺點

對內存不友好,過期鍵過期也可能不會被刪除,導致所占的內存也不會釋放。甚至可能會出現內存泄露的現象,當存在很多過期鍵,而這些過期鍵又沒有被訪問到,這會可能導致它們會一直保存在內存中,造成內存泄露。

定期刪除

由於定時刪除會占用太多的 CPU 時間片,影響服務器的響應時間和吞吐量。並且惰性刪除浪費太多的內存,有內存泄漏的風險。因此定期刪除策略是這兩策略的折衷策略。

  • 優點

定期刪除策略每隔一段時間執行一次刪除過期鍵操作,並通過限制刪除操作執行的時長和頻率來減少刪除操作對 CPU 時間的影響。

定時刪除策略有效地減少了因為過期鍵帶來的內存浪費。

什么是緩存穿透?

緩存穿透是指緩存和數據庫中都沒有數據的情況下,客戶端不斷發起請求,導致數據庫壓力過大。

什么是緩存擊穿?

緩存擊穿是指緩存過期之后,瞬時間並發客戶端特別多查詢同一條數據的情況下,導致數據庫壓力過大。

什么是緩存雪崩?

緩存雪崩是指緩存中大量的不同數據同時過期,此時查詢大量的數據,導致數據庫壓力過大。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM