开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 10 天,点击查看活动详情
大家好,我是半夏之沫 😁😁 一名金融科技领域的JAVA系统研发😊😊
我希望将自己工作和学习中的经验以最朴实,最严谨的方式分享给大家,共同进步👉💓👈
👉👉👉👉👉👉👉👉💓写作不易,期待大家的关注和点赞💓👈👈👈👈👈👈👈👈
👉👉👉👉👉👉👉👉💓关注微信公众号【技术探界】 💓👈👈👈👈👈👈👈👈
前言
LRU(Least Recently Used) 算法其实就是将最近被访问距离当前最久的数据删除。
当Redis使用的内存将超过maxmemory时,Redis会根据maxmemory_policy淘汰策略来决定将哪些数据淘汰掉。使用到LRU算法的淘汰策略如下所示。
- volatile-lru。对设置了过期时间的数据生效,使用LRU算法删除数据;
- allkeys-lru。对所有数据生效,使用LRU算法删除数据。
本篇文章将对Redis 6.0.16版本中的LRU算法实现原理进行分析。
正文
一. 算法细节
server.h文件中有redisObject的定义,如下所示。
#define LRU_BITS 24
typedef struct redisObject {
unsigned type:4;
unsigned encoding:4;
unsigned lru:LRU_BITS;
int refcount;
void *ptr;
} robj;
当某个key被使用时,都会把当前秒时间的后24bit赋值给key对应的redisObject的lru字段(后续简称为key的lru)。
所以计算一个key的空闲时间的方法就是将当前秒时间的后24bit减去key的lru,但是这样会引入一个问题,会出现当前秒时间的后24bit小于key的lru,所以计算一个key的空闲时间时需要先判断当前秒时间的后24bit和key的lru的大小关系,如果当前秒时间的后24bit小于key的lru,那么计算key的空闲时间的公式如下所示。
当前秒时间的后24bit + (24位最大值 - key的lru)
二. 源码分析
计算redisObject.lru的逻辑在evict.c文件的estimateObjectIdleTime() 方法中,如下所示。
unsigned long long estimateObjectIdleTime(robj *o) {
// 获取当前秒时间的后24位
unsigned long long lruclock = LRU_CLOCK();
if (lruclock >= o->lru) {
// 当前秒时间的后24位大于等于redisObject.lru时直接相减得到空闲时间
return (lruclock - o->lru) * LRU_CLOCK_RESOLUTION;
} else {
// 否则需要当前秒时间的后24位 + (24bit最大值 - redisObject.lru)
return (lruclock + (LRU_CLOCK_MAX - o->lru)) *
LRU_CLOCK_RESOLUTION;
}
}
上面的estimateObjectIdleTime() 方法中会调用LRU_CLOCK() 方法获取当前秒时间的后24位,其实现如下。
#define LRU_CLOCK_RESOLUTION 1000
unsigned int LRU_CLOCK(void) {
unsigned int lruclock;
// 一旦定时器每次执行的间隔时间小于等于LRU_CLOCK_RESOLUTION
// 则当前秒时间的后24位使用server.lruclock
if (1000/server.hz <= LRU_CLOCK_RESOLUTION) {
lruclock = server.lruclock;
} else {
// 否则真正获取一次当前系统的秒时间并取后24位
lruclock = getLRUClock();
}
return lruclock;
}
上面的LRU_CLOCK_RESOLUTION是LRU算法中的时钟分辨率,定义在server.h文件中,默认为1000,单位是ms。
最后给出上面出现的获取系统的秒时间的后24位的getLRUClock() 方法的实现,如下所示。
unsigned int getLRUClock(void) {
// 获取当前系统秒时间的后24位
return (mstime()/LRU_CLOCK_RESOLUTION) & LRU_CLOCK_MAX;
}
三. 流程图
整体的LRU算法的一个流程图如下所示。
大家好,我是半夏之沫 😁😁 一名金融科技领域的JAVA系统研发😊😊
我希望将自己工作和学习中的经验以最朴实,最严谨的方式分享给大家,共同进步👉💓👈
👉👉👉👉👉👉👉👉💓写作不易,期待大家的关注和点赞💓👈👈👈👈👈👈👈👈
👉👉👉👉👉👉👉👉💓关注微信公众号【技术探界】 💓👈👈👈👈👈👈👈👈
开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 10 天,点击查看活动详情