Redis的过期策略是什么

Redis的过期策略是什么

本篇内容介绍了“Redis的过期策略是什么”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

保存过期时间

Redis可以为每个key设置过期时间,会将每个设置了过期时间的key放入一个独立的字典中。

typedefstructredisDb{intid;//id是数据库序号,为0-15(默认Redis有16个数据库)longavg_ttl;//存储的数据库对象的平均ttl(timetolive),用于统计dict*dict;//存储数据库所有的key-valuedict*expires;//存储key的过期时间dict*blocking_keys;//blpop存储阻塞key和客户端对象dict*ready_keys;//阻塞后push响应阻塞客户端存储阻塞后push的key和客户端对象dict*watched_keys;//存储watch监控的的key和客户端对象}redisDb;

dict 用来维护一个 Redis 数据库中包含的所有 Key-Value 键值对,expires则用于维护一个 Redis 数据库中设置了失效时间的键(即key与失效时间的映射)。注意这里的失效时间是用毫秒的时间戳表示的,比如2022-01-02 22:45:02过期则value为1641134702000

当我们使用expire命令设置一个key的失效时间时,Redis 首先到 dict 这个字典表中查找要设置的key是否存在,如果存在就将这个key和失效时间添加到 expires 这个字典表。

当我们使用setex命令向系统插入数据时,Redis 首先将 Key 和 Value 添加到 dict 这个字典表中,然后将 Key 和失效时间添加到 expires 这个字典表中。注意setex只能用于字符串

简单地总结来说就是,设置了失效时间的key和具体的失效时间全部都维护在 expires 这个字典表中。

设置过期时间

expire的使用

expire命令的使用方法如下: expire key ttl(单位秒)

127.0.0.1:6379>expirename2#2秒失效(integer)1127.0.0.1:6379>getname(nil)127.0.0.1:6379>setnamezhangfeiOK127.0.0.1:6379>ttlname#永久有效(integer)-1127.0.0.1:6379>expirename30#30秒失效(integer)1127.0.0.1:6379>ttlname#还有24秒失效(integer)24127.0.0.1:6379>ttlname#失效(integer)-2

Redis有四个不同的命令可以用于设置键的生存时间(键可以生存多久)或过期时间(键什么时候会被删除):

expire 命令用于将键key的生存时间设置为ttl

pexpire 命令用于将键key的生存时间设置为ttl毫秒

expireat 命令用于将键key的过期时间设置为timestamp所指定的数时间戳

pexpireat 命令用于将键key的过期时间设置为timestamp所指定的毫秒数时间戳

注意expire、pexpire、expireat最终实现都是通过pexpireat实现的,也就是说无论客户端执行哪个命令,都会Redis都会转换成pexpireat命令执行。所以expires字典中存的时间是用毫秒时间戳表示的键的过期时间。

过期策略

如果一个键过期了,那什么时候被删除呢?

有三种过期策略

  • 定时删除:在设置键的过期时间的同时,创建一个定时器,让定时器在键的过期时间来临时,立即执行对键的删除操作。(创建定时器删除

  • 惰性删除:放任键的过期不管,但是每次从键空间中获取键时,都检查取得的键是否过期,如果过期的话,就删除该键;如果没有过期,就返回该键。(使用的时候删除

  • 定期删除:每隔一段时间,程序就对数据库进行一次检查,删除里面过期的键。至于要删除多少过期键,以及要检查多少个数据库,则有算法决定。(定期扫描删除

定时删除

  • 优点

1、对内存最友好:通过使用定时器,可以保证过期的键会尽可能快地被删除,释放所占内存

  • 缺点

1、对cpu最不友好:在过期键比较多的情况下,删除过期键这一行为可能会占用相当一部分cpu的时间,对服务器的响应时间和吞吐量造成影响。

惰性删除

  • 优点

1、对cpu最友好:只有在取出键的时候才会对过期键进行检查,即不需要cpu定期扫描,也不需要创建大量的定时器。

  • 缺点

1、对内存最不友好:如果一个键已经过期,但是后面不会被访问到的话,那么就一直保留在数据库中。如果这样的键过多,无疑会占用很大的内存。

定期删除

定期删除是上面的定时删除和惰性删除的一中折中方案。

  • 优点

1、定期删除每隔一段时间执行一次过期键操作,并通过限制删除操作执行的时长和频率来减少删除操作对cpu时间的影响。

2、通过删除过期键,能有效的减少因为过期键而带来的内存浪费

  • 缺点 难以确定删除操作执行的时长和频率

1、如果删除操作执行得太频繁,或者执行的时间太长,定期删除策略就会退化成定时删除,以至于占用太多cpu的执行时间。

2、如果删除操作执行的时间太少,或执行时间太短,定期删除策略又会和惰性删除一样,出现内存浪费。

Redis的过期策略

Redis使用是惰性删除定期删除两种策略:通过配好使用这两种策略,服务器可以很好地在合理使用cpu时间和避免浪费内存空间之间取得平衡。

惰性删除策略的实现

过期键的惰性删除删除策略由db.c/expireIfNeeded函数实现,所有读写数据库的Redis命令在执行之前都会调用expireIfNeed函数对输入键进行检查:

  • 如果键已经过期,那么expireIfNeeded函数将键删除

  • 如果键未过期,那么expireIfNeeded函数不做操作

命令调用expireIfNeeded函数过程如下图

另外因为每个被访问的键都可能被删除,所以每个命令都必须能同时处理键存在以及不存在的情况。 下图表示get命令的执行过程

定期删除策略的实现

过期键的定期删除策略由redis.c/activeExpireCycle函数实现,每当Redis的服务器周期性操作redis.c/serverCron函数执行时,activeExpireCycle函数就会被调用,它在规定时间内,分多次遍历服务器中各个数据库。

Redis 默认每秒进行 10 次过期扫描,过期扫描不会遍历过期字典中所有的 key, 而是采用了一种简单的贪心策略,步骤如下。

(1)从过期字典中随机选出 20个 key。

(2)删除这 20 个 key 中已经过期的 key。

(3)如果过期的 key的比例超过 1/4,那就重复步骤 (1)。 同时,为了保证过期扫描不会出现循环过度,导致结程卡死的现象,算法还增加了扫描时间的上限,默认不会超过 25ms。

假设一个大型的 Redis 实例中所有的 key 在同一时间过期了,会出现怎样的结果呢?

消耗cpu

Redis 会持续扫描过期字典(循环多次),直到过期字典中过期的key变得稀疏,才会停止(循环次数明显下降)。

导致请求卡顿或超时

当客户端请求到来时,服务器如果正好进入过期扫描状态,客户端的请求将会等待至少 25ms 后才会进行处理,如果客户端将超时时间设置得比较短,比如 10ms,那么就会出现大量的连接因为超时而关闭 ,业务端就会出现很多异常

所以一定要注意过期时间,如果有大批量的key过期,要给过期时间设置一个随机范围,而不能全部在同一时间过期。

“Redis的过期策略是什么”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注亿速云网站,小编将为大家输出更多高质量的实用文章!

发布于 2022-01-05 23:26:44
收藏
分享
海报
0 条评论
30
上一篇:C#异步多线程使用中的常见问题有哪些 下一篇:C++控制权限关键字protected怎么用
目录

    0 条评论

    本站已关闭游客评论,请登录或者注册后再评论吧~

    忘记密码?

    图形验证码