按照官方文档的介绍,Redis所实现的是一种近似的LRU算法,每次随机选取一批数据进行LRU淘汰,而不是针对所有的数据,通过牺牲部分准确率来提高LRU算法的执行效率。
Redis内部只使用Hash表缓存了数据,并没有创建一个专门针对LRU算法的双向链表,之所以这样处理也是因为以下几个原因:
筛选规则,Redis是随机抽取一批数据去按照淘汰策略排序,不再需要对所有数据排序;
性能问题,每次数据访问都可能涉及数据移位,性能会有少许损失;
内存问题,Redis对内存的使用一向很“抠门”,数据结构都很精简,尽量不使用复杂的数据结构管理数据;
策略配置,如果线上Redis实例动态修改淘汰策略会触发全部数据的结构性改变,这个Redis系统无法承受的。
redisObject是Redis核心的底层数据结构,成员变量lru字段用于记录了此key最近一次被访问的LRU时钟(server.lruclock),每次Key被访问或修改都会引起lru字段的更新。
cstruct redisObject {
unsigned type:4; // 对象类型,占用4位,用于标识不同类型的对象
unsigned encoding:4; // 对象编码方式,占用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; // 指向实际存储对象数据的指针
};
unsigned int LRU_CLOCK(void) {
unsigned int lruclock;
if (1000/server.hz <= LRU_CLOCK_RESOLUTION) {
atomicGet(server.lruclock,lruclock);
} else {
lruclock = getLRUClock();
}
return lruclock;
}
本文作者:yowayimono
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!