上一講提到,緩存的容量老是小於後端數據庫的。隨着業務系統的使用,緩存數據會撐滿內存空間,該怎麼處理呢?算法
本節咱們來學習內存淘汰機制。在Redis 4.0以前有6種內存淘汰策略,以後又增長2種,一共8種,以下圖所示:數據庫
對於TTL、Random比較好理解,下面學習一下LRU和LFU算法。後端
LRU算法,全稱Least Recently Used。緩存
其中MRU端指最近訪問的數據;LRU端指最先訪問的數據。dom
被訪問的數據和新插入的數據會移到MRU端,空間滿了後從LRU端刪除。這樣一來,最先訪問的數據會逐漸被淘汰。性能
但LRU算法也有其缺點:學習
而Redis對其進行簡化:spa
當再次淘汰數據時,會挑選數據放到第一次淘汰時的候選集合,要求小於候選集合中最小的lru值才能加入。code
其中maxmemory-samples
配置項:表示選出的個數N。能夠經過如下命令進行設置:server
CONFIG SET maxmemory-samples 100
LFU算法是在LRU策略基礎上,爲每一個數據增長一個計數器,來統計這個數據的訪問次數。
使用LFU策略篩選淘汰數據時,根據數據的訪問次數進行篩選,把訪問次數最低的數據淘汰。若是兩個數據訪問次數相同,再比較兩個數據的訪問時效性,把更久的數據淘汰。
LFU也是使用RedisObject的lru字段來實現。
把24bit的lru字段拆分紅兩部分:
當LFU策略淘汰數據時,Redis在候選集合中,根據lru字段的後8bit選擇訪問次數最小的數據進行淘汰。若是訪問次數相同,再根據lru字段的前16bit值大小,選擇更久的數據進行淘汰。
Redis並無採用數據每被訪問一次,就+1的規則,而是採用一個相似於隨機+1的規則:
double r = (double)rand()/RAND_MAX; ... double p = 1.0/(baseval*server.lfu_log_factor+1); if (r < p) counter++;
經過設置 lfu_log_factor
配置項來控制計數器值增長的速度,避免counter很快到255。下圖是 lfu_log_factor
設置不一樣值時,counter的增加狀況: