1. 判断一个key的有效期
# 查看num这里key的有效期
# 返回值有三种 正数:剩余有效期秒数 -1:永久有效 -2:已被删除或不存在或已过期
127.0.0.1:6379> ttl num
(integer) -1
- TTL和PTTL两个命令都是通过计算键的过期时间和当前时间之间的差来实现的
- 检查给定键是否存在于过期字典,如果存在,那么取得键的过期时间
- 检查当前UNIX时间戳是否大于键的过期时间,如果是的话,那么键已经过期。
2. 原理
- redis中有一个类似于hash结构的expires,其中
3. 定时删除
- 为设置了过期时间的key创建一个定时器,当过期时间到达时,定时器任务立即执行对键的删除操作
- 用处理器时间换内存
- 优点
- 缺点
-
- CPU压力大,如果当前CPU负载量高会很影响指令吞吐量
4. 惰性删除
- 数据到达过期时间不做任何处理,等下次访问该数据时
- 优点:节约CPU性能 ; 缺点:内存压力大
5. 定期删除
- 周期性轮询redis库中的时效性数据,采用随机抽取的策略。利用过期数据占比的方式控制删除频度
- 特点
- 随机抽查,重点抽查
# 默认每次检查的数据库数量
DEFAULT_DB_NUMBERS = 16
# 默认每个数据检查的键数量
DEFAULT_KEY_NUMBERS = 20
# 全局变量,记录检查进度
current_db = 0
def activeExpireCycle():
# 初始化要检查的数据库数量
# 如果服务器的数据库数量比DEFAULT_DB_NUMBERS小
# 那么以服务器的数据库数量为准
if server.dbnum < DEFAULT_DB_NUMBERS:
db_numbers = server.dbnum
else:
db_numbers = DEFAULT_DB_NUMBERS
# 遍历各个数据库
for i in range(db_numbers):
# 如果current_db的值等于服务器的数据库数量
# 表示检查程序已经遍历了服务器的所有数据库一次
# 将current_db重置为0,开始新一轮遍历
if current_db == server.dbnum:
current_db = 0
# 获取当前要处理的数据库
redisDb = server.db[current_db]
# 将数据库索引增1,指向下一个要处理的数据库
current_db += 1
# 检查数据库键
for j in range(DEFAULT_KEY_NUMBERS):
# 如果数据库中没有过期键,那么跳过这个数据库
if redisDb.expires.size() == 0: break
# 随机获取一个带有过期时间的键
key_with_ttl = redisDb.expires.get_random_key()
# 检查键是否过期,如果过期就删除
if is_expired(key_with_ttl):
delete_key(key_with_ttl)
# 已经达到本次删除操作时间上限,停止处理
if reach_time_limit(): return
6. redis中的删除策略
2. AOF、RDB、复制时对过期间的处理
2.1 RDB备份于载入时
- RDB备份时,程序会对数据库中的键进行检查,不会将过期的键进行备份
- RDB载入时
- 主服务器载入时,会检查备份的键是否过期,只将未过期的键载入数据库
2.2 AOF备份
- AOF备份时,无论键过没过期,都会备份(会备份过期时间)
- 当过期键被惰性删除或定期删除之后,会向AOF文件追加一条DEL命令,来显示记录该键已删除
2.3 AOF重写
- 程序对数据库的所有键进行检查,不会将过期键保存到重写后的AOF文件中
2.4 主从复制
- 从服务器的过期键删除受主服务器控制
- 主服务器在删除过期键的时候,会向所有从服务器发送一条DEL命令。
- 从服务器只有收到了主服务器发来的DEL命令,才会删除过期间。
- 当客户端读取从服务器的过期键时,如果从服务器没有收到主服务器的过期键删除命令,即使这个键过期了,从服务器仍然正常返回过期键。