Redis缓存淘汰策略

八个淘汰策略

  • volatile-random
  • volatile-lru
  • volatile-lfu
  • volatile-ttl
  • noeviction
  • allkeys-lru
  • allkeys-random
  • allkeys-lfu

LRU

标准LRU算法是由双向链表及Hash表实现,具体代码实现可以参考LRU算法

Redis中的LRU算法实现有所变化:

  1. Reids没有使用双向链表维护数据页的访问顺序,只使用了全局哈希表缓存数据
  2. 随机抽取N个数据,通过redisObject结构体中的lru值,取出最小的值进行淘汰。

lru字段有24bit。

	#define LRU_BITS 24
	typedef struct redisObject {
		unsigned type:4;
		unsigned encoding:4;
		unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
								* LFU data (least significant 8 bits frequency
								* and most significant 16 bits access time). */
		int refcount;
		void *ptr;
	} robj;

优点

没有严格按照最近最久未使用来进行淘汰,但是采用随机及lru思想,节省了大量的指针内存及调整操作时间,更多地考虑了空间及性能的优化。

LFU

标准LFU算法优先根据使用次数进行优先级排序,同次数下使用LRU算法进行优先级排序。

参考redisObject结构中的lru字段,当使用LFU算法时,lru字段低8位会用来存储访问频次,高16位存储更新时间。

  • 低8位
    8位最大值只有255,故此8位实际存放的是优化后的值,并且会随时间衰减。值比较小容易被回收,故初始默认值是大于零的值LFU_INIT_VAL(默认5)。
频次增长算法如下:
double r = (double)rand()/RAND_MAX;   // 0到1的随机数
double p = 1.0/(baseval*server.lfu_log_factor+1);
if (r < p) counter++;

baseval是计数器当前的值,lfu_log_factor是配置项。

不同lfu_log_factor值与频次递增效果如下:
不同lfu_log_factor值与频次递增效果

  • 高16位
    类似lru的24bit,只是精度降低了。
posted @ 2023-11-16 21:20  kiper  阅读(1)  评论(0编辑  收藏  举报