面試官問:Redis 緩存淘汰策略有哪些?
我們知道:Redis是基于內存的,面試官問:
- 生產環境Redis內存如何分配?
- Redis鍵過期了如何刪除?
- ......
本小節不僅適用于工作,也是面試的高頻問題。
文章導讀
Redis內存分析
1.Redis默認內存是多少?
在 64bit 系統下,默認不限制內存大小,不設置內存大小和maxmemory = 0表示不限制 Redis 內存使用
2.如何查看Redis最大內存是多少?
命令行:
127.0.0.1:6379> config get maxmemory
1) "maxmemory"
2) "0"
配置文件 redis.conf:
# maxmemory <bytes>
3.如何查看Redis內存使用情況?
127.0.0.1:6379> info memory
4.如何配置和修改?
臨時方案,通過命令修改:
127.0.0.1:6379> config set maxmemory 104857600
OK
127.0.0.1:6379> config get maxmemory
1) "maxmemory"
2) "104857600"
永久方案,通過配置文件:
5.生產環境如何配置?
建議:一般取物理內存的3/4
Redis過期鍵刪除?
我們知道,redis一般會設置過期時間。那么這些鍵過期了是立刻從內存中刪除嗎?
通常,鍵刪除會有不同的策略。
1.立刻刪除
立即刪除能保證過期鍵值會在過期后馬上被刪除,其所占用的內存也會隨之釋放。但是刪除操作會占用cpu的時間,造成CPU額外的壓力。
redis.conf 中,通過調整過期鍵的檢測頻率:
# The range is between 1 and 500, however a value over 100 is usually not
# a good idea. Most users should use the default of 10 and raise this up to
# 100 only in environments where very low latency is required.
hz 10
但是這會產生大量的性能消耗,同時也會影響數據的讀取操作。
2.惰性刪除
數據到達過期時間,不做處理。等下次訪問該數據時:
- 如果未過期,返回數據 ;
- 發現已過期,刪除,返回不存在。
惰性刪除策略的缺點是,它對內存是最不友好的。如果一個鍵已經過期,而這個鍵又仍然保留在redis中,那么只要這個過期鍵不被刪除,它所占用的內存就不會釋放。
#開啟憜性淘汰
lazyfree-lazy-eviction=yes
3.定期刪除
這種方案有效規避上述兩種極端情況, 定期刪除策略的難點是確定刪除操作執行的時長和頻率:
- 如果刪除操作執行得太頻繁或者執行的時間太長,定期刪除策略就會退化成立即刪除策略。
- 如果刪除操作執行得太少,或者執行的時間太短,定期刪除策略又會和惰性刪除束略一樣,出現浪費內存的情況。
- 因此,如果采用定期刪除策略的話,服務器必須根據情況,合理地設置刪除操作的執行時長和執行頻率。
Redis內存淘汰策略
基于上述的了解,假如:
- 定期刪除時,從來沒有被抽查到
- 惰性刪除時,也從來沒有被點中使用過
上述兩個步驟,依然會有大量過期的key堆積在內存中,導致redis內存空間緊張或者很快耗盡。
因此,有沒有一個更好的兜底方案......?這就是要講的淘汰策略
1.LRU和LFU區別?
(1) LRU(Least Recently Used,最近最少使用頁面置換算法)
假設我們有一個容量為3的LRU緩存,訪問數據的順序如下:
- 訪問數據1,緩存中現在有:[1]
- 訪問數據2,緩存中現在有:[1, 2]
- 訪問數據3,緩存中現在有:[1, 2, 3]
- 再次訪問數據1,緩存中現在有:[2, 3, 1](因為1被重新訪問,它被移到了列表的末尾)
- 訪問數據4,由于緩存已滿,最不常用的數據2將被淘汰,緩存中現在有:[3, 1, 4]
原理:如果數據最近被訪問過,那么在不久的將來它很可能再次被訪問。因此,LRU會淘汰最長時間未被訪問的數據。
適用場景:適用于最近被訪問的數據在未來某個時間點很可能再次被訪問。
(2) LFU(Least Frequently Used,最近最不常用頁面置換算法)
假設我們有一個容量為3的LFU緩存,訪問數據的順序如下:
- 訪問數據1,計數器:{1: 1}
- 訪問數據2,計數器:{1: 1, 2: 1}
- 訪問數據1,計數器:{1: 2, 2: 1}
- 訪問數據3,計數器:{1: 2, 2: 1, 3: 1}
- 訪問數據1,計數器:{1: 3, 2: 1, 3: 1}
- 訪問數據4,由于緩存已滿,訪問次數最少的數據2將被淘汰,計數器:{1: 3, 3: 1, 4: 1}
原理:LFU算法會跟蹤每個頁面在特定時間段內被訪問的頻率。當需要淘汰頁面時,LFU算法會淘汰在該時間段內訪問次數最少的頁面。
適用場景:LFU算法適用于那些訪問模式可能隨時間變化的場景,或者訪問頻率能夠較好地反映頁面重要性的情況。
(3) 小結
- LRU關注數據的最近訪問時間,淘汰最長時間未被訪問的數據。
- LFU關注數據的訪問頻率,淘汰訪問次數最少的數據。
2.Redis有哪些淘汰策略?
redis.config 配置文件中,
# volatile-lru -> Evict using approximated LRU, only keys with an expire set.
# allkeys-lru -> Evict any key using approximated LRU.
# volatile-lfu -> Evict using approximated LFU, only keys with an expire set.
# allkeys-lfu -> Evict any key using approximated LFU.
# volatile-random -> Remove a random key having an expire set.
# allkeys-random -> Remove a random key, any key.
# volatile-ttl -> Remove the key with the nearest expire time (minor TTL)
# noeviction -> Don't evict anything, just return an error on write operations.
解釋下:
- volatile-lru:使用近似的最近最少使用(LRU)算法淘汰鍵。但是,只有那些設置了過期時間的鍵(即“volatile”鍵)才會被考慮淘汰。
- allkeys-lru:使用近似的LRU算法淘汰任何鍵,無論它們是否設置了過期時間。
- volatile-lfu:使用近似的最少頻率使用(LFU)算法淘汰鍵。同樣,只有設置了過期時間的鍵會被考慮。
- allkeys-lfu:使用近似的LFU算法淘汰任何鍵,不考慮它們是否設置了過期時間。
- volatile-random:隨機淘汰一個設置了過期時間的鍵。
- allkeys-random:隨機淘汰任何鍵,不論它們是否設置了過期時間。
- volatile-ttl:淘汰具有最短剩余生存時間(TTL)的鍵,即那些最接近過期時間的鍵。
- noeviction:不淘汰任何鍵。當內存達到最大容量時,Redis將不會進行任何淘汰操作,而是在寫入新數據時返回錯誤。
3.生產如何選擇淘汰策略?
在生產環境中選擇緩存淘汰策略時,通常需要根據應用的具體需求和數據特性來定。這里給出常見案例:
(1) 電商平臺的商品推薦
電商平臺需要為用戶展示個性化的商品推薦,其中熱門商品的訪問頻率較高??蛇x擇:LFU(Least Frequently Used)
redis-cli config set maxmemory-policy allkeys-lfu
因為LFU策略可以保留訪問頻率高的商品,確保推薦列表中展示用戶最可能感興趣的商品。
(2) 金融交易平臺的實時數據
金融交易平臺需要提供實時的股票價格和交易數據,數據的實時性至關重要。過期的時價被淘汰。
可選擇:TTL(Time To Live)結合LRU(Least Recently Used)
redis-cli config set maxmemory-policy volatile-lru
TTL確保數據在一定時間后自動過期,而LRU保證最近訪問的數據被優先保留。
(3) 電信運營商的用戶數據管理
電信運營商需要處理和緩存大量用戶的通話記錄、短信記錄等,用戶通常更關心最近的通信記錄。
可選擇:LRU(Least Recently Used)
redis-cli config set maxmemory-policy allkeys-lru
因為LRU策略可以確保最近生成的通話記錄和短信記錄被優先緩存。
(4) 社交媒體平臺的用戶動態
社交媒體平臺需要為用戶展示好友的最新動態和帖子,用戶通常對最新動態感興趣。
可選擇:LRU
redis-cli config set maxmemory-policy allkeys-lru
因為LRU可以保證最新的帖子被優先展示。
好了,今天就聊到這里,讀者可依據實際情況擇優選擇策略。