设置键过期时间的命令
- EXPIRE
- PEXPIRE
- EXPIREAT
- PEXPIREAT
保存键的过期时间
在redisDb中,用一个名为expire的字典保存了所有键的过期时间,称它为过期字典。
- 过期字典的键是一个指针,指向了键空间的某个数据库键对象
- 过期字典的值是一个long long类型,保存了数据库键的过期时间,即一个毫秒精度的unix时间戳
/* Redis database representation. There are multiple databases identified * by integers from 0 (the default database) up to the max configured * database. The database number is the 'id' field in the structure. */ typedef struct redisDb { dict *dict; /* The keyspace for this DB */ dict *expires; /* Timeout of keys with a timeout set */ ...... } redisDb;
过期键的判定
- 检测过期字典里是否存在键,如果不存在则返回false,存在则取过期时间
- 检测当前unix时间戳是否大于过期时间,大于表示键过期,否则未过期
过期键删除策略
定时删除
设置键过期时间的同时,设置一个定时器在过期时间来临时删除键
- 优点是保证了过期键会尽可能快的删掉,释放占用的内存
- 删除操作会占用cpu时间,在有大量键需要删除,而内存不紧张但cpu时间紧张的情况下,会对响应时间和吞吐量造成影响
惰性删除
放任过期键不管,每次获取键时都得检查是否过期,过期则删除,未过期则返回值
- 优点是对cpu时间优化,保证只有在非做不可的时候才会删除,而不会在其它无关的过期键浪费时间
- 缺点是对内存不友好,如果存在非常多的过期键会占用大量内存
定期删除
每隔一段时间,对数据库检查删除过期键,而删除多少,检查多少个数据库由算法决定。定期删除实际上是上面两种算法的折中。
- 优点是可以限制删除操作执行的时长和频次,减少对cpu时间的影响;定期删除能有效减少内存浪费
- 缺点是难以确定时长和频次,如果删除太频繁或者执行时间太长,会占用cpu资源;如果删除频次太少或者执行时间太短,又会造成内存浪费
redis的删除策略,惰性删除和定期删除的结合
惰性删除的实现
所有读写数据库的redis命令执行前,都会调用expireIfNeeded函数来做检查,如果输入键未过期则不做处理,如果过期则expireIfNeeded函数将它删除
定期删除的实现
周期性调用activeExpireCycle函数,分多次遍历服务器中的各个数据库,从数据库字典中随机检查一部分键的过期时间,并且删除其中的过期键
过期键对RDB,AOF,复制的影响
RDB
- 生成RDB文件时,已过期的键不会保存
- 载入RDB文件时,如果是主服务器不会载入过期键,如果是从服务器会载入,因为主从复制时从服务器也会清空
AOF
- AOF文件写入时,当过期键被删除时,会向AOF文件追加一条DEL命令显示删除该记录
- AOF文件重写时,过期键不会重写到AOF文件中
复制
在复制模式下,从服务器的过期删除动作由主服务器控制 - 主服务器删除过期键,会显示通知所有从服务器删除,通过发送DEL命令的方式
- 从服务器执行读命令时碰到过期键不会惰性删除,而是会返回数据给客户端
- 从服务器只有接收了DEL命令时,才会删除过期键