1. 過期 key 處理
Redis 之所以性能強,最主要的原因就是基于記憶體存盤,然而單節點的 Redis 其記憶體大小不宜過大,會影響持久化或主從同步性能,
我們可以通過修改組態檔來設定 Redis 的最大記憶體:
maxmemory 1gb
當記憶體使用達到上限時,就無法存盤更多資料了,為了解決這個問題,Redis 提供了一些策略實作記憶體回收:
先要了解的是:redis 是一個存盤鍵值資料庫系統,那它原始碼中是如何存盤所有鍵值對的呢?
Redis 本身是一個典型的 key-value 記憶體存盤資料庫,因此所有的 key、value 都保存在之前學習過的 Dict 結構中,不過在其 database 結構體中,有兩個 Dict:一個用來記錄 key-value;另一個用來記錄 key-TTL,

內部結構

- dict 是 hash 結構,用來存放所有的 鍵值對
- expires 也是 hash 結構,用來存放所有設定了 過期時間的 鍵值對,不過它的 value 值是過期時間
這里有兩個問題需要我們思考:
- Redis 是如何知道一個 key 是否過期呢?
- 利用兩個 Dict 分別記錄 key-value 對及 key-ttl 對,是不是 TTL 到期就立即洗掉了呢?
總結:Redis的過期洗掉策略就是:惰性洗掉和定期洗掉兩種策略配合使用
惰性洗掉
惰性洗掉:顧明思議并不是在 TTL 到期后就立刻洗掉,而是在訪問一個 key 的時候,檢查該 key 的存活時間,如果已經過期才執行洗掉,
周期洗掉
周期洗掉:顧明思議是通過一個定時任務,周期性的抽樣部分過期的 key,然后執行洗掉,執行周期有兩種:
- Redis 服務初始化函式 initServer () 中設定定時任務,按照 server.hz 的頻率來執行過期 key 清理,模式為 SLOW
- Redis 的每個事件回圈前會呼叫 beforeSleep () 函式,執行過期 key 清理,模式為 FAST
SLOW 模式規則:

- 執行頻率受 server.hz 影響,默認為 10,即每秒執行 10 次,每個執行周期 100ms,
- 執行清理耗時不超過一次執行周期的 25%. 默認 slow 模式耗時不超過 25ms
- 逐個遍歷 db,逐個遍歷 db 中的 bucket,抽取 20 個 key 判斷是否過期
- 如果沒達到時間上限(25ms)并且過期 key 比例大于 10%,再進行一次抽樣,否則結束
FAST 模式規則(過期 key 比例小于 10% 不執行 ):
- 執行頻率受 beforeSleep () 呼叫頻率影響,但兩次 FAST 模式間隔不低于 2ms
- 執行清理耗時不超過 1ms
- 逐個遍歷 db,逐個遍歷 db 中的 bucket,抽取 20 個 key 判斷是否過期
- 如果沒達到時間上限(1ms)并且過期 key 比例大于 10%,再進行一次抽樣,否則結束
2記憶體淘汰策略
①、設定Redis最大記憶體
在組態檔redis.conf 中,可以通過引數 maxmemory

不設定該引數默認是無限制的,但是通常會設定其為物理記憶體的四分之三
②、設定記憶體淘汰方式
當現有記憶體大于 maxmemory 時,便會觸發redis主動淘汰記憶體方式,通過設定 maxmemory-policy
有如下幾種淘汰方式:
volatile-lru:設定了過期時間的key使用LRU演算法淘汰;allkeys-lru:所有key使用LRU演算法淘汰;volatile-lfu:設定了過期時間的key使用LFU演算法淘汰;allkeys-lfu:所有key使用LFU演算法淘汰;volatile-random:設定了過期時間的key使用隨機淘汰;allkeys-random:所有key使用隨機淘汰;volatile-ttl:設定了過期時間的key根據過期時間淘汰,越早過期越早淘汰;noeviction:默認策略,當記憶體達到設定的最大值時,所有申請記憶體的操作都會報錯(如set,lpush等),只讀操作如get命令可以正常執行;
比較容易混淆的有兩個:
? LRU(Least Recently Used),最少最近使用,用當前時間減去最后一次訪問時間,這個值越大則淘汰優先級越高,
? LFU(Least Frequently Used),最少頻率使用,會統計每個 key 的訪問頻率,值越小淘汰優先級越高,
* LRU、LFU和volatile-ttl都是近似隨機演算法;
使用下面的引數maxmemory-policy配置淘汰策略:
#組態檔
maxmemory-policy noeviction
#命令列
127.0.0.1:6379> config get maxmemory-policy
1) "maxmemory-policy"
2) "noeviction"
127.0.0.1:6379> config set maxmemory-policy allkeys-random
OK
127.0.0.1:6379> config get maxmemory-policy
1) "maxmemory-policy"
2) "allkeys-random"
Redis 的資料都會被封裝為 RedisObject 結構:

LFU 的訪問次數之所以叫做邏輯訪問次數,是因為并不是每次 key 被訪問都計數,而是通過運算:
- 生成 0~1 之間的亂數 R
- 計算 (舊次數 * lfu_log_factor + 1),記錄為 P
- 如果 R < P ,則計數器 + 1,且最大不超過 255
- 訪問次數會隨時間衰減,距離上一次訪問時間每隔 lfu_decay_time 分鐘,計數器 -1
本文由
傳智教育博學谷教研團隊發布,如果本文對您有幫助,歡迎
關注和點贊;如果您有任何建議也可留言評論或私信,您的支持是我堅持創作的動力,轉載請注明出處!
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/539499.html
標籤:其他
