當Redis內存超過物理內存限制時,內存數據會和磁盤產生頻繁的交換,讓Redis的性能急劇下降。所以在生產環境,這種交換行爲是不允許的。
maxmemory參數是用來配置最大內存大小的,如果超過了maxmemory,Redis提供瞭如下幾種可選策略,用來設置maxmemory-policy。
1、丟棄策略概覽
- noeviction:不會繼續服務處理del之外的寫請求,讀請求可以繼續進行,這是默認策略;
- volatile-lru:根據近似lru算法進行淘汰,但不會丟棄沒有設置過期時間的key;
- volatile-ttl:比較有過期時間的key的壽命,壽命短的先淘汰;
- volatile-random:從設置了過期時間的key中隨機選擇key進行淘汰;
- allkeys-lru:和volatile-lru相比,淘汰範圍從所有設置了過期時間的key,擴展到了所有的key(包含沒有設置過期時間的key);
- allkeys-random:和volatile-random相比,淘汰範圍從所有設置了過期時間的key,擴展到了所有的key(包含沒有設置過期時間的key)。
2、近似LRU算法
LRU算法需要消耗大量額外的內存,所以Redis採用的,實際上是一種近似LRU算法。Redis給每個key增加了一個字段,24bit,用於描述最後一次被訪問的時間戳。
當Redis執行寫操作時,發現內存超出maxmemory,就會指定LRU淘汰算法。隨機採樣出5(可以設置)個key,然後淘汰掉最舊的key;如果淘汰後內存還是超出maxmemory,就繼續淘汰,指定內存低於maxmemory爲止。
每次採樣多少,是通過maxmemory_samples進行設置的。
Redis增加了淘汰池,以提升LRU算法的效果。淘汰池是一個數組,每一次淘汰循環中,新的隨機得出的key列表,會和淘汰池中的key列表進行融合,淘汰掉最舊的一個key之後,保留剩餘較舊的key列表在池中,等待下一次淘汰。
算法流程如下:
- redis執行寫操作時,發現內存大小超過maxmemory配置的值,觸發丟棄過程;
- redis執行對緩存的數據進行採樣,採樣數量取決於maxmemory_samples的配置;
- 根據每個key最後一次被訪問的時間戳排序,從採樣中選出時間最久的key;
- 將採樣中時間最久的key放入到淘汰池,並淘汰掉淘汰池中時間最久的key。