KeyDB中的子key过期

这篇博客介绍了KeyDB如何在Redis的基础上实现子key过期功能,通过使用哈希表优化性能,探讨了sortedvector与hash表的优缺点,并定制了hash表以支持EXPIREMEMBER命令,提升了过期key和子key的查找效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

来源:https://docs.keydb.dev/blog/2021/06/08/blog-post/

在Redis社区有一个很早就提出来的功能:让SET和HASH数据类型的子成员有自己的过期时间。Redis没有接受该需求,可能是考虑到在没有内置命令的情况下实现该功能比较困难,但KeyDB(Redis的一个分支)专注于提供易于使用的高性能Redis,所以实现了该功能。

KeyDB添加子key过期的最初尝试是对每个expire都添加一个用于子key过期的vector,但这会导致某些性能问题。我们接下来将了解这些问题的原因,以及我们如何使用更复杂的数据结构,如哈希表,来解决这些问题。

EXPIREMEMBER命令

KeyDB通过新命令EXPIREMEMBER实现子key过期。该命令的参数是key, 子key及其过期时间,在过期时间到达后将子key从key中删除,其他的子key保持不变。以下是Hash数据类型的例子:

Keydb-cli> HSET myhash f1 v1 f2 v2 f3 v3

integer3

Keydb-cli> EXPIREMEMBER myhash f3 10

integer1

Keydb-cli> TTL myhash f3

integer10

10秒后

Keydb-cli> HGET myhash f1

“v1”

Keydb-cli> HGET myhash f2

“v2”

Keydb-cli> HGET myhash f3

nil)

在上面的例子中,我们将成员f3设置为10秒后到期,10秒后它就被删除了,但其他成员都还在。

KeyDB如何实现EXPEMEMBER

KeyDB以两种不同的方式过期key和子key: 被动过期和主动过期。每当访问key或子key时,被动过期就会触发:检查该key或子key是否过期并将其删除。主动过期是由KeyDB在运行期间定期执行,KeyDB会遍历即将过期的key和子key,并删除已经过期的key和子key。

在实现EXPEMEMBER命令时,一个重要的考虑因素是如何存储key和子key的过期时间。存储方式可以让主动过期算法快速遍历最有可能已经到期的key和子key,也可以让被动过期快速找到相关的key和子key,同时对KeyDB内存使用的影响降至最低。KeyDB使用按过期时间排序的vector,但这会导致被动过期的查找期间线性增加,从而对其他操作产生巨大影响。为了解决这个问题,我们考虑使用hash表,它提供了恒定时间的查找。以下是使用sorted vector和hash表的优缺点。

Sorted vector的优点:

  1. 主动过期算法可以轻松遍历即将过期的key和子key,使KeyDB能够确保快速删除不经常访问的过期key和子key。
  2. Vector是一种内存高效的数据结构,能最小化存储过期时间所需的内存量。

Sorted vector的缺点:

  1. 添加新的过期时间和修改现有的过期时间需要O(log(n))的搜索,以确保将其放到vector中正确的位置,这会导致过期命令随着即将过期key和子key数量的增加而减慢。
  2. 被动过期需要查找特定key的过期时间,在按过期时间排序的vector中,这需要O(n)的搜索,这会导致在访问有大量即将过期子key的key时大幅减慢。

Hash表的优点:

  1. 添加新的过期时间和修改现有的过期时间可以在O(1)的时间内快速完成。
  2. 被动过期需要查找特定key的过期时间,也可以在O(1)的时间内快速完成。

Hash表的缺点:

  1. Hash表增加了在主动到期算法中遍历即将过期key和子key的复杂度,从而增加了删除不经常访问的过期key和子key的时间。
  2. Hash表的内存效率不是很高,通常在负载因子约为2/3的情况下达到最佳性能。在存储等量过期信息的条件下,hash表的内存使用量比sorted vetor多50%。

下面的图表比较了有1000000条记录的hash数据结构(其中n个子key即将过期)分别用sorted vector和hash表实现子key过期时的性能(operations/second)。基于图表中的对比,我们选择了使用hash表来存储过期信息。

https://docs.keydb.dev/img/blog/2021-05-31/opsvsexpires.png

EXPIREMEMBER命令定制的hash表

如前文所分析,使用hash表的主要缺点是增加了在主动到期算法中遍历即将过期key和子key的复杂度。所以我们对用于EXPIREMEMBER命令的hash表做了如下定制:

  1. 按到期时间对hash表中的单个bucket进行排序,每个bucket都有固定的最大记录数,因此保持它们排序的成本为O(1)。
  2. 创建一个智能iterator,该iterator按顺序访问上述bucket。这样可以尽量减少在遍历hash表时碰到没有过期的key和子key。

综上所述,使用hash表可以明显地提高被动过期的性能,并通过定制的hash表尽量减少对主动过期算法的性能影响,从而快速查找过期的key和子key。我们最终获得了最佳实践,使KeyDB在不影响整体性能的情况下实现了EXPIREMEMBER命令,支持了子key过期。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值