為了更好的利用內存,使Redis存儲的都是緩存的熱點數據,Redis設計了相應的內存淘汰機制(也叫做緩存淘汰機制)
通過maxmemory
內存淘汰的過程
- 客戶端發起了需要申請更多內存的命令(如set)
- Redis檢查內存使用情況,如果已使用的內存大於maxmemory則開始根據用戶配置的不同淘汰策略來淘汰內存(key),從而換取一定的內存
- 如果上面都沒問題,則這個命令執行成功
6 種數據淘汰策略
默認為no-eviction策略
- volatile-lru
從已設置過期時間的數據集(server.db[i].expires)中挑選最近最少使用的數據淘汰
- allkeys-lru
從數據集(server.db[i].dict)中挑選最近最少使用的數據淘汰
- volatile-ttl
從已設置過期時間的數據集(server.db[i].expires)中挑選將要過期的數據淘汰
- volatile-random
從已設置過期時間的數據集(server.db[i].expires)中任意選擇數據淘汰
- allkeys-random
從數據集(server.db[i].dict)中任意選擇數據淘汰
- no-enviction
禁止驅逐數據,永遠不過期,僅對寫操作返回一個錯誤,默認為該項
Redis 確定驅逐某個鍵值對后,會刪除這個數據,並將這個數據變更消息發布到本地(AOF 持久化)和從機(主從連接)
LRU 數據淘汰機制
實際上Redis實現的LRU並不是可靠的LRU,也就是名義上我們使用LRU算法淘汰鍵,但是實際上被淘汰的鍵並不一定是真正的最久沒用的,這里涉及到一個權衡的問題,如果需要在全部鍵空間內搜索最優解,則必然會增加系統的開銷,Redis是單線程的,也就是同一個實例在每一個時刻只能服務於一個客戶端,所以耗時的操作一定要謹慎。為了在一定成本內實現相對的LRU,早期的Redis版本是基於采樣的LRU,也就是放棄全部鍵空間內搜索解改為采樣空間搜索最優解。自從Redis3.0版本之后,Redis作者對於基於采樣的LRU進行了一些優化,目的是在一定的成本內讓結果更靠近真實的LRU。
TTL 數據淘汰機制
Redis 數據集數據結構中保存了鍵值對過期時間的表,即 redisDb.expires,在使用 SET 命令的時候,就有一個鍵值對超時時間的選項。
從過期時間 redisDB.expires 表中隨機挑選幾個鍵值對,取出其中 ttl 最大的鍵值對淘汰。同樣TTL淘汰策略並不是所有過期時間的表中最快過期的鍵值對,而只是隨機挑選的幾個鍵值對。
隨機淘汰
在隨機淘汰的場景下獲取待刪除的鍵值對,隨機找hash桶再次hash指定位置的dictEntry即可
總結
Redis中的淘汰機制(LRU和TTL)都是非精確算法實現的,主要從性能和可靠性上做平衡,所以並不是完全可靠,在了解Redis淘汰策略之后還應在平時多主動設置或更新key的expire時間,主動刪除沒有價值的數據,提升Redis整體性能和空間