命令
在Redis中,设置键的过期时间有四个命令EXPIRE, PEXPIRE, EXPIREAT, PEXPIREAT
。其中前三个命令都最终转换成第四个实现。即
保存
Redis数据库使用两个字典保存数据:dict和expires。dict保存所有的键值对数据,expires保存所有键及其过期时间。
expires的键对象是一个指针,指向某个键对象,也就是说expires共享dict中的键对象,不单独再存储一份键空间,节约空间。expires的值是一个long long整型,保存过期时间的Unix时间戳。(PEXPIREAT
)
PERSIST
取消键的过期时间,实际做的工作就是解除expires字典中键值对的关联。
TTL
返回某个键的剩余过期时间,通过过期时间减去当前时间得来。
删除策略
有三种过期键删除策略:
- 定时删除:设置定时器(timer),一旦发现键过期,立即删除。这对于CPU紧张型的场景不友好。假设键很多,CPU将花费很多时间在键的删除上了。
-
惰性删除:不理睬过期键。当读写操作时再去判断键是否过期
这种方法的好处就是不用CPU过多的干涉,但是缺点在于Redis是内存数据库,对空间比较敏感。如果内存中存在大量的过期键而不清除,浪费了许多空间,产生内存泄漏。
- 定期删除:每隔一段时间去检查并清除过期键。这是上两种方法的折中。既不要CPU实时清扫,又不会让过期键一直占用空间。难点在于选择合适的频率。
Redis使用惰性删除+定期删除的策略。
RDB, AOF,复制过程中对过期键的处理
- RDB:调用
BGSAVE
或SAVE
时,Redis过滤过期键,不会把过期键包含在快照中。载入RDB文件时,主服务器会过滤过期键,从服务器不做检查,全部载入。不过不用担心,在主从同步时,从服务器会全部清空,与主服务器保持一致。故过期键不会对RDB持久化产生影响。 - AOF:当过期键被策略删除后,向AOF中追加一条
DEL
命令,显式指明该键已经被删除。AOF重写也会过滤过期键。 - 复制:主服务器控制从服务器上的过期键。假设主从服务器上各有一个已过期的键message。
如果向从服务器发送GET message请求,那么从服务器照常返回这个键对应的值。
如果向主服务器发送GET message请求,那么主服务器发现这个键已经过期,就会向客户端返回空,删除这个键,同时给从服务器发送一条DEL message
命令,让它也把这个键删除。