redis内存回收——过期淘汰
Posted A_BCDE_
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了redis内存回收——过期淘汰相关的知识,希望对你有一定的参考价值。
redis内存设置过大时会增加同步等操作的复杂度
DB结构
/* Redis database representation. There are multiple databases identified
* by integers from 0 (the default database) up to the max configured
* database. The database number is the 'id' field in the structure. */
typedef struct redisDb
dict *dict; /* keyspace,存储所有key,value */
dict *expires; /* 存储设置过期时间的key,ttl */
dict *blocking_keys; /* Keys with clients waiting for data (BLPOP)*/
dict *blocking_keys_unblock_on_nokey; /* Keys with clients waiting for
* data, and should be unblocked if key is deleted (XREADEDGROUP).
* This is a subset of blocking_keys*/
dict *ready_keys; /* Blocked keys that received a PUSH */
dict *watched_keys; /* WATCHED keys for MULTI/EXEC CAS */
int id; /* Database ID */
long long avg_ttl; /* Average TTL, just for stats */
unsigned long expires_cursor; /* Cursor of the active expire cycle. */
list *defrag_later; /* List of key names to attempt to defrag one by one, gradually. */
clusterSlotToKeyMapping *slots_to_keys; /* Array of slots to keys. Only used in cluster mode (db 0). */
redisDb;
删除策略
惰性删除
访问时,检查过期时间,删除
已过期但不访问的数据,永远存在,占据内存
周期删除
定期抽样部分key检查过期时间,删除
SLOW
redis初始化时设置定期任务
- 默认每秒执行10次,每个周期100ms
- 执行清理耗时不超过一次执行周期的25%
- 遍历所有db(每个db类似于一个数组)的所有bucket(数组下标index),抽取20个key检查(记录本次遍历位置,下次定时任务从该位置继续)
- 如果没有达到时间上限(25ms)&过期key比例大于10%,再进行一次抽样,否则结束
FAST
redis每个事件执行之前
- 两次fast间隔大于2ms,执行清理不超过1ms
- 遍历所有db(每个db类似于一个数组)的所有bucket(数组下标index),抽取20个key检查(记录本次遍历位置,下次定时任务从该位置继续)
- 如果没有达到时间上限(1ms)&过期key比例大于10%,再进行一次抽样,否则结束
淘汰策略
redis主动删除key,释放内存
-
noeviction:只返回错误,不会删除任何key。该策略是Redis的默认淘汰策略,一般不会选用。
-
volatile-ttl:将设置了过期时间的key中即将过期(剩余存活时间最短)的key删除掉。
-
volatile-random:在设置了过期时间的key中,随机删除某个key。
-
allkeys-random:从所有key中随机删除某个key。
-
volatile-lru:基于LRU算法,从设置了过期时间的key中,删除掉最近最少使用的key。
-
allkeys-lru:基于LRU算法,从所有key中,删除掉最近最少使用的key。该策略是最常使用的策略。
-
volatile-lfu:基于LFU算法,从设置了过期时间的key中,删除掉最不经常使用(使用次数最少)的key。
-
allkeys-lfu:基于LFU算法,从所有key中,删除掉最不经常使用(使用次数最少)的key。
struct redisObject
unsigned type:4;//对象类型
unsigned encoding:4;//编码方式
unsigned lru:LRU_BITS; /* LRU time 最近一次访问时间 秒为单位
* LFU data 低八位记录逻辑访问次数
高16位记录最近一次访问时间 分钟为单位). */
int refcount;//对象引用计数器
void *ptr;//指针,指向不同数据类型的数据,真实数据
;
淘汰过程
- 将设置ttl的key抽取部分存入pool
- 将pool中所有key按照值升序排列
- 从pool中按序删除
- 避免排序,效率更高
redis内存回收
1.定时过期expilre expire key TTL 10定时器 主动淘汰 2.惰性过期 被动淘汰 3getCommand expireIfNeed() 设置内存上线 set memory 上线 activeExpireCycle() redis使用了 惰性过期 + 定期过期 达到了最大内存上线后根据内存淘汰规则 # volatile-lru -> remove the key with an expire set using an LRU algorithm # allkeys-lru -> remove any key according to the LRU algorithm # volatile-random -> remove a random key with an expire set # allkeys-random -> remove a random key, any key # volatile-ttl -> remove the key with the nearest expire time (minor TTL) # noeviction -> don\'t expire at all, just return an error on write operations 不在接收新的指令存进内存
以上是关于redis内存回收——过期淘汰的主要内容,如果未能解决你的问题,请参考以下文章