Skip to content

Redis 的过期键删除策略

Redis

对于 Redis 服务器来说,内存资源非常宝贵,如果一些过期键一直不被删除,就会造成资源浪费,因此需要考虑一个问题:如果一个键过期了,它什么时候会被删除呢?

1. 常见的删除策略

常见的删除策略有以下 3 种:

  • 定时删除

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

  • 惰性删除

放任过期键不管,每次从键空间中获取键时,检查该键是否过期,如果过期,就删除该键,如果没有过期,就返回该键。

  • 定期删除

每隔一段时间,程序对数据库进行一次检查,删除里面的过期键,至于要删除哪些数据库的哪些过期键,则由算法决定。其中定时删除和定期删除为主动删除策略,惰性删除为被动删除策略。

1.1 定时删除策略

定时删除策略通过使用定时器,定时删除策略可以保证过期键尽可能快地被删除,并释放过期键占用的内存。因此,定时删除策略的优缺点如下所示:

  • 优点:对内存非常友好
  • 缺点:对 CPU 时间非常不友好

举个例子,如果有大量的命令请求等待服务器处理,并且服务器当前不缺少内存,如果服务器将大量的 CPU 时间用来删除过期键,那么服务器的响应时间和吞吐量就会受到影响。也就是说,如果服务器创建大量的定时器,服务器处理命令请求的性能就会降低,因此 Redis 目前并没有使用定时删除策略。

1.2 惰性删除策略

惰性删除策略只会在获取键时才对键进行过期检查,不会在删除其它无关的过期键花费过多的 CPU 时间。因此,惰性删除策略的优缺点如下所示:

  • 优点:对 CPU 时间非常友好
  • 缺点:对内存非常不友好

举个例子,如果数据库有很多的过期键,而这些过期键又恰好一直没有被访问到,那这些过期键就会一直占用着宝贵的内存资源,造成资源浪费。

1.3 定期删除策略

定期删除策略是定时删除策略和惰性删除策略的一种整合折中方案。定期删除策略每隔一段时间执行一次删除过期键操作,并通过限制删除操作执行的时长和频率来减少删除操作对 CPU 时间的影响,同时,通过定期删除过期键,也有效地减少了因为过期键而带来的内存浪费。

2. Redis 使用的过期键删除策略

Redis 服务器使用的是惰性删除策略和定期删除策略。

2.1 惰性删除策略的实现

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

  • 如果输入键已经过期,那么将输入键从数据库中删除
  • 如果输入键未过期,那么不做任何处理

以上描述可以使用如下流程图表示:

1604020124801-fe3cc039-5706-426e-9f2f-c5bff7458727.png

2.2 定期删除策略的实现

过期键的定期删除策略由 activeExpireCycle 函数实现,每当 Redis 服务器的周期性操作 serverCron 函数执行时,activeExpireCycle 函数就会被调用,它在规定的时间内,分多次遍历服务器中的各个数据库,从数据库的 expires 字典中随机检查一部分键的过期时间,并删除其中的过期键。activeExpireCycle 函数的大体流程为:

函数每次运行时,都从一定数量的数据库中随机取出一定数量的键进行检查,并删除其中的过期键,比如先从 0 号数据库开始检查,下次函数运行时,可能就是从 1 号数据库开始检查,直到 15 号数据库检查完毕,又重新从 0 号数据库开始检查,这样可以保证每个数据库都被检查到。

INFO

可能有的面试官还会问,每次随机删除哪些 key 呢?可以提下 LRU 算法(Least Recently Used 最近最少使用)。

3. RDB 对过期键的处理

3.1 生成 RDB 文件

在执行 SAVE 命令或者 BGSAVE 命令创建一个新的 RDB 文件时,程序会对数据库中的键进行检查,已过期的键不会被保存到新创建的 RDB 文件中。举个例子,如果数据库中包含 3 个键 k1、k2、k3,并且 k2 已经过期,那么创建新的 RDB 文件时,程序只会将 k1 和 k3 保存到 RDB 文件中,k2 则会被忽略。

3.2 载入 RDB 文件

在启动 Redis 服务器时,如果服务器只开启了 RDB 持久化,那么服务器将会载入 RDB 文件:

  • 如果服务器以主服务器模式运行,在载入 RDB 文件时,程序会对文件中保存的键进行检查,未过期的键会被载入到数据库中,过期键会被忽略。
  • 如果服务器以从服务器模式运行,在载入 RDB 文件时,文件中保存的所有键,不论是否过期,都会被载入到数据库中。

因为主从服务器在进行数据同步(完整重同步)的时候,从服务器的数据库会被清空,所以一般情况下,过期键对载入 RDB 文件的从服务器不会造成影响。

4. AOF 对过期键的处理

4.1 AOF 文件写入

如果数据库中的某个键已经过期,并且服务器开启了 AOF 持久化功能,当过期键被惰性删除或者定期删除后,程序会向 AOF 文件追加一条 DEL 命令,显式记录该键已被删除。举个例子,如果客户端执行命令 GET message 访问已经过期的 message 键,那么服务器将执行以下 3 个动作:

  • 从数据库中删除 message 键
  • 追加一条 DEL message 命令到 AOF 文件
    -向执行 GET message 命令的客户端返回空回复

4.2 AOF 文件重写

在执行 AOF 文件重写时,程序会对数据库中的键进行检查,已过期的键不会被保存到重写后的 AOF 文件中。

5. 复制功能对过期键的处理

在主从复制模式下,从服务器的过期键删除动作由主服务器控制:

  • 主服务器在删除一个过期键后,会显式地向所有从服务器发送一个 DEL 命令,告知从服务器删除这个过期键。
  • 从服务器在执行客户端发送的读命令时,即使发现该键已过期也不会删除该键,照常返回该键的值。
  • 从服务器只有接收到主服务器发送的 DEL 命令后,才会删除过期键。

更新: 2020-10-30 09:10:53
原文: <https://www.yuque.com/fcant/notes/kaqibb&gt;

最近更新