Code前端首页关于Code前端联系我们

Redis过期key处理和内存回收真的太棒了!

terry 2年前 (2023-09-26) 阅读数 57 #数据库

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前端网发表,如需转载,请注明页面地址。

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

热门