Redis过期key处理和内存回收真的太棒了!
1。过期key处理
Redis之所以有强大的性能,主要原因在于它是基于内存存储的。但单节点Redis的内存大小不宜太大,否则会影响持久化或主从同步性能。
我们可以通过更改配置文件来设置Redis的最大内存:
maxmemory 1gb
当内存使用达到上限时,就无法再存储数据了。为了解决这个问题,Redis提供了一些策略来实现内存回收:
首先需要了解的是:Redis是一个键值存储数据库系统,那么它是如何存储源中的所有键值对的呢?代码? ?
Redis本身就是一个典型的key-value内存存储数据库,所以所有的key和value都存储在之前学过的Dict结构中。然而,数据库结构中有两种Dict:一种用于记录键值;另一种用于记录键值。另一个用于记录密钥TTL。
内部结构
- dict 是一个哈希结构,用于存储所有键值对
- expires 也是一个哈希结构,用于存储所有设定过期时间的键值对,但是value 就是过期时间
我们需要思考两个问题:
- Redis 如何知道某个 key 是否过期了?
- 使用两个Dict分别捕获键值对和键-ttl对。 TTL 过期后是否会立即删除?
总结:Redis过期移除策略是:懒惰移除和定期移除策略配合使用
懒惰移除
懒惰移除:顾名思在TTL过期后不会立即移除,而是在打开一个key后检查key 的生存时间,只有在过期时才将其删除。
定期删除
定期删除:顾明思使用计划作业定期采样部分过期的密钥,然后将其删除。有两个执行周期:
- Redis服务初始化函数initServer()设置一个定时任务,按照server.hz的频率执行过期key的清理。该模式是 SLOW beforeSleep() 在每个 Redis 事件循环之前调用。 )函数,执行过期key的清理,模式为FAST
SLOW模式规则:
- 执行频率受server.hz影响,默认值为10,即运行10次每秒,每个执行周期持续 100 ms。
- 执行清理所花费的时间不超过执行周期的 25%。默认慢速模式耗时不超过25毫秒
- 一一遍历数据库,一一遍历数据库中的Bucket,提取20个key判断是否过期
- 如果没有则达到时限达到(25 ms)且过期密钥占比大于10%,再次进行采样,否则
FAST模式规则结束(过期密钥占比小于10%,不执行):
- 执行频率受 beforeSleep() 调用频率影响,但两次 FAST 模式之间的间隔不小于 2 ms
- 执行清理所需的时间不超过 1 ms
- 逐个数据库,一一遍历db中的bucket,提取20个key判断是否过期
- 如果未达到时间限制(1ms)且过期key比例大于10 %,则再进行一次采样,否则终止
2 内存淘汰策略
①,设置Redis最大内存
在redis.conf配置文件中,可以通过maxmemory参数来淘汰最大内存设置内存:
不设定该参数默认是无限制的,但是通常会设定其为物理内存的四分之三
②,设置内存淘汰方式
当现有内存大于maxmemory时,redis会激活主动内存淘汰方式。设置 maxmemory-policy
执行以下操作。淘汰方式不同:
易失性-lru
:使用LRU算法淘汰设置过期时间的key;allkeys-lru
:使用LRU算法消除所有key;volatile-lfu
:使用LFU算法淘汰具有设定过期时间的key;allkeys-lfu
:使用LFU算法消除所有key;volatile-random
:设置过期时间的Key会被随机淘汰。 ;allkeys-random
:所有key随机消除;volatile-ttl
:设置了过期时间的Key,根据过期时间进行淘汰。越早过期,就越早被淘汰;noeviction
:默认策略:当内存达到设置的最大值时,所有应用到内存的操作都会报错(如set、lpush等),而只读操作如get命令可能会报错正常执行;
有两个比较容易混淆:
LRU(最近的)y 已使用),最近最少使用时间是当前时间减去上次访问时间。值越大,淘汰优先级越高。
LFU(最不常用),最不常用。统计每个按键的访问频率。值越小,淘汰优先级越高。
* LRU、LFU和volatile-ttl都是近似随机算法;
使用以下参数 maxmemory-policy 配置淘汰策略:
#配置文件
maxmemory-policy noeviction
#命令行
127.0.0.1:6379> config get maxmemory-policy
1) "maxmemory-policy"
2) "noeviction"
127.0.0.1:6379> config set maxmemory-policy allkeys-random
OK
127.0.0.1:6379> config get maxmemory-policy
1) "maxmemory-policy"
2) "allkeys-random"
Redis 数据封装在 RedisObject 结构体中:
对 LFU 的访问次数称为逻辑访问次数代替为了对每次使用密钥进行计数,使用以下操作:
- 生成 0 到 1 之间的随机数 R
- 计算(旧数 * lfu_log_factor + 1),记录为 P
- 如果 R
- ,随着时间的推移,访问次数会减少。自上次访问时间起每 lfu_decay_time 分钟,计数器 -1
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。