redis-内存回收机制

发布于:2024-05-05 ⋅ 阅读:(28) ⋅ 点赞:(0)

在 Redis 的源码中,redisDb 结构体用于表示一个 Redis 数据库实例。结构体大致如下

typedef struct redisDb {
    dict *dict;                 // 存储键值对的字典
    dict *expires;              // 存储键的过期时间的字典
    dict *blocking_keys;        // 阻塞键的字典
    dict *ready_keys;           // 准备就绪键的字典
    dict *watched_keys;         // 被 WATCH 命令监视的键的字典
    int id;                     // 数据库的编号
    long long avg_ttl;          // 平均过期时间
    unsigned long expires_cursor; // 过期字典的迭代器游标
} redisDb;
  1. dict: 这是一个指向字典的指针,字典用来存储数据库中的所有键值对。这是数据库的主数据结构。(字典是一个用哈希表实现的数据结构用于保存key和value)

  2. expires: 这也是一个指向字典的指针,用于存储具有过期时间的键。键是数据库中的键,而值是过期时间(UNIX 时间戳)。(不存储内容,存储key和其过期时间)

  3. blocking_keys: 这个字典存储那些正在阻塞某些命令(如 BLPOP)的键。键为阻塞的键,值为阻塞这些键的客户端列表。(某些对数据执行的命令会有阻塞效果,这些数据被保存在这里)

  4. ready_keys: 存储那些已准备就绪以供阻塞命令处理的键。(命令条件达成,不需要阻塞了)

  5. watched_keys: 当使用事务和 WATCH 命令时,这个字典会存储被监视的键。如果这些键在事务执行之前被修改,事务将被中断。(使用watch监听某一数据,该数据会被保存在这,比如执行事务时可以先监听一个数据,当这个数据发生更改,则事务作废)

  6. id: 数据库的索引编号,Redis 配置中可以设置多个数据库,这个编号就是用来标识每个数据库的。

  7. avg_ttl: 这表示数据库中所有设置了过期时间的键的平均过期时间。

  8. expires_cursor: 这是用于渐进式地清理过期键的内部迭代器的游标。(redis在进行周期性删除时,该值则记录了清理任务的当前执行位置,因为redis数据庞大,无法一次清理完成,需要记录上一次的清理位置,再次清理时,在这个位置以后继续清理,这个位置的记录就叫游标)

过期key的淘汰有两种方式

1.惰性删除:这种删除方式是当我们使用这个数据时才回去检查过期时间,如果过期,则删除该缓存。

2.周期删除:周期删除是指redis按一定频率抽查设置了过期时间的key是否过期,并且由expiers_cursor配合记录清理位置,它包括两种模式

slow模式:这种模式下按照server.hz配置的参数的频率执行清理任务,假如说将其设置为10,那么该模式下,redis将每秒执行十次清理,并且每次执行时间不能超过25ms

fast模式:该模式下将在一个循环中不断执行清理操作,并且保证两次清理任务之间间隔不低于2ms,并且每次清理操作执行不能超过1ms

当redis内存爆满时,他将依据既定的内存淘汰策略来清理内存,包括如下:

noeviction : 不淘汰任何 key ,但是内存满时不允许写入新数据,默认就是这种策略。
volatile-ttl : 对设置了 TTL 的 key ,比较 key 的剩余 TTL 值, TTL 越小越先被淘汰
allkeys-random :对全体 key ,随机进行淘汰。也就是直接从 db->dict 中随机挑选
volatile-random :对设置了 TTL 的 key ,随机进行淘汰。也就是从 db->expires 中随机挑选。
allkeys-lru : 对全体 key ,基于 LRU 算法进行淘汰
volatile-lru : 对设置了 TTL 的 key ,基于 LRU 算法进行淘汰
allkeys-lfu : 对全体 key ,基于 LFU 算法进行淘汰
volatile-lfu : 对设置了 TTL 的 key ,基于 LFI 算法进行淘汰

ttl表示过期时间

其中allkeys表示对全体key,volatile表示设置了过期时间的key,lru和lfu分别是两种算法,random表示随机

LRU ( Least Recently Used ),最近最少使用。用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高。
LFU ( Least Frequently Used ),最少频率使用。会统计每个 key 的访问频率,值越小淘汰优先级越高。

无论是LRU还是LFU,在进行淘汰key的比较时都是比较redisobject结构体中的lru属性的值,而lru属性在LRU相关模式下会记录最近访问时间戳,在LFU模式化会用一个简单的算法记录访问频率。


网站公告

今日签到

点亮在社区的每一天
去签到