如何为Redis中list中的项设置过期时间

时间:2022-06-16 23:33:20

Redis是一个伟大的工具,用来在内存中存储列表是很合适的。

不过,如果你想要快速搜索列表,同时需要让列表中每项都在一定时间后过期,应该怎么做呢?

首先,当然不能使用不同的类似的key存储数据,然后使用keys命令来获取所有类似key的数据。这样的开销是不可接受的。

Redis并没有直接提供方法做这件事,但是这是可以做到的!虽然最后用的未必是Redis的List数据结构。

我接下来会展示给你看。

问题

最近,我遇到一个问题,我有一个数据列表,需要用它来制作折线图,我准备使用API返回这个数据列表,然后在前端绘图。

这个数据列表本身是挺大的,然后它还会一直更新,所以放在数据库是不合适的,我计算过从数据库取回需要10s。所以我决定使用redis。

碰到一个问题,就是数据列表中的数据,如果超过一定时间的话我是不需要了,否则这个列表会变得无比巨大。所以我需要redis对列表中的每个项都设置过期时间。

然后我在网上找到这篇文章,它描述了两种办法。

在讲解这两种办法之前,你需要明白redis的两个数据结构:

  • Redis的集合:“无序的字符串集合”,它的项有下面的特点
    • 唯一的(如果加入重复的数据,redis会默默的拒绝)
    • 无序,并且不可以用任何方法(在redis中)排序
  • Redis有序集合:“有序的字符串集合“,它的项有下面的特点:
    • 和集合一样,每个项都是唯一的
    • 拥有积分(项的积分并不必须是唯一的)
    • 根据积分排序(有索引)

这两个集合,都不可以对其中的项设置过期时间。当然,你可以对整个集合设置过期时间。

两种解决方法

有序集合

查询有序集合是非常快的,因为redis将一个列表转换成了集合,所以当我们访问它的时候,它已经是排好序的了。

根据Redis文档的描述:

“Sorted sets are implemented via a dual-ported data structure containing both a skip list and a hash table, so every time we add an element Redis performs an O(log(N)) operation. That’s good, but when we ask for sorted elements Redis does not have to do any work at all, it’s already all sorted”

当然,你不可以对有序集合中每个项设置TTL。

你可以通过score对有序集合进行查询,我们可以利用这个地方来形成一个解决方案:

对于加入到有序集合的每个项,我们都将它的score设置为Unix Timestamp,这个timestamp代表它的过期时间。然后,我们加入一个定时任务,定时移除那些过期的数据

多个集合以及TTL

这个方案使用普通的集合。

因为不能对集合中每项都设置TTL,但是可以对整个集合设置TTL。所以,我们可以将每个时间段的数据放在一个集合中。然后对这个集合设置过期时间。