redis 的內(nèi)存清理

redis.png

一個示例

? redis中,set一個值,有效期為 3600 秒,這個值會什么時候釋放?

常規(guī)理解為,在 3600 秒到期后,redis服務(wù)會自動清除,

也就意味著,redis需要有一個機制,每隔一個時間極短的時間段去掃描所有的key,判斷是否到期并刪除,這種開銷是巨大的

過期刪除

對于設(shè)置了過期時間的 key,刪除有兩個機制共同管理

? 惰性刪除(訪問時釋放)

觸發(fā)時機:當(dāng)客戶端訪問該 key(如執(zhí)行 GET、TTL、EXISTS 等命令)時。

行為:Redis 檢測到該 key 已過期,立即物理刪除該 key,釋放內(nèi)存,然后返回 nil。如果沒被訪問,即使過了 100 秒,key 仍可能留在內(nèi)存中。

?? 關(guān)鍵點:如果這個 key 過期后再也沒有被訪問過,它會一直占用內(nèi)存,直到被其他機制清理。

? 定期刪除(后臺定時釋放)

觸發(fā)條件:Redis 后臺每隔 100ms(默認配置)會啟動一次(后臺任務(wù))定期掃描任務(wù),隨機抽取部分帶過期時間的 key 檢查。

行為:從所有設(shè)置了過期時間的 key 中隨機抽取 n 個;刪除其中已過期的 key;

?? 關(guān)鍵點:這是一個概率性、非實時的清理過程。所以你設(shè)置了過期時間的 key 可能在這一輪掃描中,沒掃描到,會在以后的任意時間點(比如 10.2s、12s、甚至更久)被清理,取決于是否被抽中。

對于后臺任務(wù)執(zhí)行間隔配置為

# 就這一行配置,默認就是 10
hz 10

hz 10代表的含義為:Redis 每秒鐘會執(zhí)行 10 輪"后臺定時任務(wù)"循環(huán),用來完成以下工作:

  1. 掃描并清理已過期的 key(這就是我們用到的)。
  2. 關(guān)閉空閑超時的客戶端連接。
  3. 更新 serverCron 里的各類統(tǒng)計信息、觸發(fā) AOF 重寫/RDB 保存的閾值判斷等。

hz的值調(diào)的越高,服務(wù)負載越大

? 還有另外一種場景,當(dāng)服務(wù)器內(nèi)存使用超過健康閾值時,如何更好的調(diào)優(yōu)?

比如服務(wù)器內(nèi)存 16G,現(xiàn)在 Redis 用了 15.9G 了,在沒錢升級配置的情況下,如何保障能夠繼續(xù) set get 使用

淘汰策略

這里先說明一個參數(shù) # maxmemory <bytes> ,官方說明為

# Set a memory usage limit to the specified amount of bytes.
# When the memory limit is reached Redis will try to remove keys
# according to the eviction policy selected (see maxmemory-policy).
#
# If Redis can't remove keys according to the policy, or if the policy is
# set to 'noeviction', Redis will start to reply with errors to commands
# that would use more memory, like SET, LPUSH, and so on, and will continue
# to reply to read-only commands like GET.

意思就是,

設(shè)置內(nèi)存使用限制為指定的字節(jié)數(shù)。當(dāng)達到內(nèi)存限制時,Redis將嘗試根據(jù)選擇的清除策略,刪除鍵;

如果Redis無法根據(jù)策略移除鍵,或策略設(shè)置為 **noeviction**,則 Redis 將開始對會占用更多內(nèi)存的命令(如SET、LPUSH等)返回錯誤,但只讀命令如GET)依舊可以正常使用。

這個解釋很清晰了,該配置默認是注釋的,也就意味著 Redis 默認允許無限使用內(nèi)存?。。?/p>

在設(shè)置了該參數(shù)后,可以根據(jù)不同種規(guī)則來清除一些 redis 的 key,從而降低內(nèi)存

參數(shù)配置示例

# 限制 Redis 最大使用內(nèi)存為 4GB
maxmemory 4gb
 
# 或者使用字節(jié)
maxmemory 4294967296

換句話來說,當(dāng) Redis 設(shè)置了 maxmemory 參數(shù)后,可選擇下面任何一個方式,來優(yōu)化內(nèi)存,具體選擇哪種(這里面學(xué)問大的很,比方說熱點數(shù)據(jù)、不常用數(shù)據(jù)的取舍),看你自己

策略名稱 說明 備注
noeviction 默認策略:內(nèi)存不足時,新寫入會報錯(OOM command not allowed) 不淘汰,默認值
allkeys-lru 從所有 key 中淘汰最近最少使用(Least Recently Used)的 key LRU算法
volatile-lru 從設(shè)置了過期時間的 key 中淘汰 LRU key LRU算法
allkeys-lfu 從所有 key 中淘汰最不經(jīng)常使用(Least Frequently Used)的 key LFU算法
volatile-lfu 從設(shè)置了過期時間的 key 中淘汰 LFU key LFU算法
allkeys-random 從所有 key 中隨機淘汰 隨機算法
volatile-random 從設(shè)置了過期時間的 key 中隨機淘汰 隨機算法
volatile-ttl 從設(shè)置了過期時間的 key 中淘汰剩余生存時間(TTL)最短的 key TTL優(yōu)先

這里補充個題外話,LRU與LFU算法區(qū)別

? LRU 最近最少使用的被淘汰。
實現(xiàn)方式:內(nèi)部可能通過鏈表的特性,尾部淘汰吧,具體實現(xiàn)不清楚

? LFU 最不經(jīng)常使用的被淘汰。
實現(xiàn)方式:每個 key 有一個訪問頻率計數(shù)器(logc),具體實現(xiàn)不清楚

?? LFU示例:對于熱點數(shù)據(jù)維度的保護策略

一個 key 每天被訪問 100 次(長期熱點),LFU 會保留它。
一個 key 只被訪問一次,即使是"最近"訪問,LFU 也會優(yōu)先淘汰。

回顧

  1. 過期刪除方式中的惰性刪除定期刪除為兩種不同機制,組合起來構(gòu)成刪除機制
  2. 過期刪除機制 和 淘汰策略 兩種之間獨立運行,互補干涉
  3. 淘汰策略只有在設(shè)置maxmemory參數(shù),且內(nèi)存達到該值時才生效
  4. 目前來說,不支持多種策略同時生效
  5. 技術(shù)不是一塵不變的,Redis 不同版本是有差異的
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容