ToB企服应用市场:ToB评测及商务社交产业平台

标题: Redis内存淘汰策略 [打印本页]

作者: 南飓风    时间: 2024-9-21 05:03
标题: Redis内存淘汰策略
redis将数据存储到内存,占用内存大小有一个设置阈值,当内存凌驾阈值时,必要根据设置的内存淘汰策略进行键的淘汰来低落内存占用,使redis可以或许继续进行写操作。这里我们参考redis7.0源码,来看一下当超出内存限定时,redis是怎么进行键淘汰的。
1. 源码入口

在源码中,这个过程在performEvictions函数中, 该函数在处理每条命令时被调用,调用链如下图:


假如redis设置了maxmemory,同时redis没有处在超时执行的lua脚本,则进行内存淘汰检查和执行对应的淘汰策略。
2. 相关设置

启动设置文件中下面这些设置项与内存淘汰息息相关:

3. 淘汰策略

淘汰策略就是指设置项maxmemory-policy。一共有8种, 从预选键的范围上来看分为3类, noeviction 体现不进行淘汰,allkeys体现在全部键上进行具体的策略,volatile体现只在设置了过期时间的键上进行具体的策略。而具体的淘汰算法实际是4种。

3.1 随机淘汰

遍历每个db,从中随机选择一个key键,留意假如前次选定了db_a,则下次会从db_a的下一个db开始选择。而随机选择的策略,对应到源码中的dictGetRandomKey(dict)。dictGetRandomKey包罗两个步骤,首先是随机选择一个hash表中的slot, 其次在slot的拉链上选择一个键。
选择slot的时候会思量rehash,不会选择刚刚rehash竣事的键。


3.2 LRU(Least Recently Used)

LRU/LFU/TTL策略在同一个条件分支下。首先是遍历每个db,调用evictionPoolPopulate函数,采样若干个键放入pool中, 由于pool中的键是按照idle从小到大排序的,然后从后往前遍历pool获取一个键,即为候选键bestKey。差异的策略实际是idle值计算方式差异。

LRU,优先淘汰最近一段时间没有被访问到的键。调用estimateObjectIdleTime获取键的idle值。
  1. typedef struct redisObject {
  2.     unsigned type:4;
  3.     unsigned encoding:4;
  4.     unsigned lru:LRU_BITS; /* LRU time (relative to global lru_clock) or
  5.                             * LFU data (least significant 8 bits frequency
  6.                             * and most significant 16 bits access time). */
  7.     int refcount;
  8.     void *ptr;
  9. } robj;
复制代码
每个键对象包罗了一个lru字段,该字段在LRU淘汰策略下体现上一次被访问时的lru时钟时间, 差值即为该键的空闲时间。同时思量到lru为24位,只能保存一段时间内的值,大概存在值的套圈,所以有了else的条件判断。

3.3 LFU(Least Frequently Used)

LFU思量到访问频率,idle = 255-LFUDecrAndReturn(o);。在LFU策略下,键对象的lru字段低8位体现访问频次,高16位体现前次访问的时间。255-访问频次作为idle的值,访问频率越低idle值越大。

3.4 TTL

直接获取键的过期时间,取最近的过期键。

4. 候选键删除

得到候选键和对应的db后,redis是怎么执行删除的呢?

4.1 同步和异步删除


async=0的时候,体现同步删除,aync=1体现异步删除。
删除键所在db假如有设置过期的键聚集,则首先尝试删除该键的过期时间,然后调用dictUnLink将键从字典中移除,但是此时并没有开释键和节点的内存。假如是异步删除则调用freeObjAsync异步删除,同时设置该节点对应的值为nullptr。最后调用dictFreeUnlinkedEntry,对于同步的情况,val不为空,会直接删除,而异步的情况,val为空,不执行删除val操作,而是在异步任务中真正的删除。
而异步删除freeObjAsync实际上还会检查对象值是否大于设置阈值以及当前是否没有被共享,两个条件都满足时才会启动后台删除线程。
这个值的计算遵照:string范例为 1,list范例返回存储元素数,set(hashtable实现)、zset(跳表实现)、hash(hashtable)返回包罗元素数

5. 总结

redis在处理线上命令时会检测内存是否超出阈值,当超出阈值时,计算本次必要开释多少内存。然后根据淘汰策略选择删除候选键,随机选择是随机选择字典的槽和拉链上的节点,lru/lfu/ttl 都是采用的近似算法,维护一个固定大小的数组,按照键的idle值从小到大排序,每次选择idle最大的键,每次也会采样指定的键来更新这个数组。选定候选键后根据设置执行同步或者异步删除。为了防止阻塞线上哀求,删除不能执行太久,所以每16次都会检查内存是否已经满足要求,满足则直接退出,检查当前删除动作是否已经超时,超市转化到后台执行。


免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4