Redis的数据是存储于内存之中,所以对内存的清理是非常重要的
Redis提出了定期数据存储的设计,也就是数据在Redis上存储是有时间限制的
本篇主要从过期键的设计来对Redis进行了解
Github issues:https://github.com/littlejoyo/Blog/issues/
Redis是基于键值对存储形式的数据库,又因为数据存储的位置在内存,所以设置键值过期并及时清理是非常重要的。
1.Redis如何设置键的过期时间?
Redis中使用
EXPIRE
进行键时间的设置使用
TTL
查询键剩余生存时间1
2
3
4
5
6
7
8
9
10redis> SET cache_page "www.google.com"
OK
redis> EXPIRE cache_page 30 # 设置过期时间为 30 秒
(integer) 1
redis> TTL cache_page # 查看剩余生存时间
(integer) 23
redis> EXPIRE cache_page 30000 # 更新过期时间
(integer) 1
redis> TTL cache_page
(integer) 29996
2.Redis下的 Expire Key
2.1 Expire Key 底层的数据结构
Redis数据库在数据库服务器中使用了redisDb数据结构,结构如下:
1 | typedef struct redisDb { |
键空间(key space):redisDb中的dict *dict成员就是将key和具体的对象(可能是string、list、set、zset、hash中任意类型之一)关联起来,存储着该数据库中所有的键值对数据。
过期字典(expires):保存数据库中所有键的过期时间,过期时间用UNIX时间戳表示,且值为long long整数
id成员:id是数据库的编号,以整型表示。
2.2 设置过期时间的命令
EXPIRE \<key> \<ttl>
:命令用于将键key的过期时间设置为ttl
秒之后PEXPIRE \<key> \<ttl>
:命令用于将键key的过期时间设置为ttl
毫秒之后EXPIREAT \<key> \<timesramp>
:命令用于将key的过期时间设置为timrestamp
所指定的秒数时间戳PEXPIREAT \<key> \<timesramp>
:命令用于将key的过期时间设置为timrestamp
所指定的毫秒数时间戳
2.3 redisDb下expires的底层
expires字段也是一个字典dict结构,字典的键为key,值为该key对应的过期时间
过期时间为long long类型整数,是以毫秒为单位的过期 UNIX 时间戳。
过期键的判定,其实是通过过期字典进行判定,步骤:
1.检查给定键是否存在于过期字典,如果存在,取出键的过期时间
2.通过判断当前UNIX时间戳是否大于键的过期时间,是的话,键已过期,相反则键未过期。
- 设置键值存储实例:使用redisDb结构存储数据图表示:(图片来源)
1
2
3
4redis> set Ccww 5 2 0
ok
redis> expire Ccww 5
ok
3.过期键删除策略
3.1 三种删除策略
定时删除:在设置键的过期时间的同时,创建一个定时任务,当键达到过期时间时,立即执行对键的删除操作
惰性删除:放任键过期不管,但在每次从键空间获取键时,都检查取得的键是否过期,如果过期的话,就删除该键,如果没有过期,就返回该键
- 定期删除:每隔一点时间,程序就对数据库进行一次检查,删除里面的过期键,至于要删除多少过期键,以及要检查多少个数据库,则由算法决定。
3.2 Redis对删除策略的选择
Redis服务器结合惰性删除和定期删除两种策略一起使用。
通过这两种策略之间的配合使用,使得服务器可以在合理使用CPU时间和浪费内存空间取得平衡点。
4.过期键注意点
4.1 如果有大量的key需要设置同一时间过期,一般需要注意什么?
如果大量的key过期时间设置的过于集中,到过期的那个时间点,redis可能会出现短暂的卡顿现象。
严重的话会出现缓存雪崩,所以一般需要在时间上加一个随机值,使得过期时间分散一些,来避免缓存集中无效的现象。
造成缓存雪崩的场景:电商首页经常会使用定时任务刷新缓存,可能大量的数据失效时间都十分集中,如果失效时间一样,又刚好在失效的时间点大量用户涌入,就有可能造成缓存雪崩
4.2 什么是缓存雪崩?
缓存雪崩可以理解为缓存同一时间大面积失效,大量请求直接请求到数据库,最后数据库承担不了巨大请求服务掉线。
举个简单的例子:如果所有首页的Key失效时间都是12小时,中午12点刷新的,我零点有个秒杀活动大量用户涌入,假设当时每秒 6000 个请求,本来缓存在可以扛住每秒 5000 个请求,但是缓存当时所有的Key都失效了。
缓存失效过程,画图理解:
5.RDB和AOF对过期键的处理
5.1 RDB
5.1.1 生成RDB文件
程序会对数据库中的键进行检查,过期的键不会被保存到新创建的 RDB 文件中。
因此数据库中的过期键不会对生成新的 RDB 文件造成影响。
5.1.2 载入 RDB 文件
这里需要分情况说明:
如果服务器以主服务器模式运行,则在载入 RDB 文件时,程序会对文件中保存的键进行检查,过期键不会被载入到数据库中。所以过期键不会对载入 RDB 文件的主服务器造成影响。
如果服务器以从服务器模式运行,则在载入 RDB 文件时,不论键是否过期都会被载入到数据库中。但由于主从服务器在进行数据同步时,从服务器的数据会被清空。所以一般来说,过期键对载入 RDB 文件的从服务器也不会造成影响。
5.2 AOF
5.2.1 AOF 文件写入
当服务器以 AOF 持久化模式运行时,如果数据库某个过期键还没被删除,那么 AOF 文件不会因为这个过期键而产生任何影响,依旧保留。
而当过期键被删除后,那么程序会向 AOF 文件追加一条 DEL 命令来显式地记录该键被删除。
5.2.2 AOF 重写
- 执行 AOF 重写过程中,也会被数据库的键进行检查,已过期的键不会被保存到重写后的 AOF 文件中。因此不会对 AOF 重写造成影响
6.主从复制对过期键的处理
当服务器运行在复制模式下,由主服务器来控制从服务器的删除过期键动作,目的是保证主从服务器数据的一致性。
那到底是怎么控制的呢?
主服务器删除一个过期键后,会向所有从服务器发送一个 DEL 命令,告诉从服务器删除这个过期键
从服务器接受到命令后,删除过期键
PS:从服务器在接收到客户端对过期键的读命令时,依旧会返回该键对应的值给客户端,而不会将其删除。
微信公众号
扫一扫关注Joyo说公众号,共同学习和研究开发技术。