限制 Redis 中列表的长度

46

我正在使用Redis列表,并将新项推送到列表中。问题是,我只需要在一个列表中保留最近的10个项目。

我使用lpush添加项目到列表中,并使用lrange获取最近的10个项目。

有没有办法在达到一定数量后删除列表中的项?因为我的列表可能会有成千上万个项目,并且这可能会导致性能问题和延迟。

谢谢!


你是如何与Redis进行接口交互的?使用CLI?Python?C#? - swasheck
应该像我以下详细回答的那样,是这样的 LTRIM list -10 -1 - kuzey beytar
6个回答

60

获取当前列表长度,并仅在长度低于10时插入,这对于大实体来说是否是更高效的解决方案呢? - bornSwift
1
@bornSwift,你的解决方案会保留最早的10个条目而不是最近的10个吗? - Terry Lewis
1
@TerryLewis,是的,说得好。我没有看到问题中的“最近”..糟糕 - bornSwift

38
您可以在每次LPUSH之后间断性地使用LTRIM无需在每次LPUSH后调用LTRIM,因为这会增加应用程序的总延迟(尽管Redis非常快,但您可以节省大量LPUSH操作)。
以下是一个伪代码,以实现大约每5次LPUSH执行一次LTRIM:
LPUSH mylist 1
random_int = some random number between 1-5
if random_int == 1:  # trim my list with 1/5 chance
   LTRIM mylist 0 10

尽管你的列表有时可能会增长到超过10个元素,但它肯定会定期被截断。 这种方法对于大多数实际用途都很好,并且可以节省很多LTRIM操作,从而保持推送速度快。


16
当一条建议来自某人在生产中的经验时,你几乎能闻到它的味道 ;) - FeignMan
你如何确定获取随机数并检查其是否为某个值,比调用“LTRIM”更加昂贵? - fiatjaf
1
@fiatjaf 主要是因为LTRIM是一项网络操作,但如果这两个操作都是单个Lua脚本的一部分,我们可能需要进行基准测试。然而,我强烈感觉,在这两种情况下,随机数操作将比LTRIM更简单。 - DhruvPathak
2
如果使用支持管道化的语言或库,则无需编写脚本来保存往返时间。 - George Leung

12

以下代码:

  • 将项目添加到列表中,
  • 将大小固定为10个,
  • 并返回最近的10个元素

交易中执行。

MULTI
LPUSH list "item1"
LTRIM list 0 9
LRANGE list 0 9
EXEC

3
@PaulT.Rawkeen为什么?使用Redis内置命令(包装在事务中)即可实现,我不认为有必要将其制作成Lua脚本。 - Roy Miloh

12

关于仅存储最近10个项目的真正解决方案,目前还没有人提及。

让我们创建一个样本列表,包含15个项目(这里仅为数字):

RPUSH list 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

现在,从列表结尾开始指定偏移量:

LTRIM list -10 -1

显示列表

LRANGE list 0 -1

 1) "6"
 2) "7"
 3) "8"
 4) "9"
 5) "10"
 6) "11"
 7) "12"
 8) "13"
 9) "14"
10) "15"

现在您可以添加新项目并运行修剪操作:

RPUSH list 16
LTRIM list -10 -1

 1) "7"
 2) "8"
 3) "9"
 4) "10"
 5) "11"
 6) "12"
 7) "13"
 8) "14"
 9) "15"
10) "16"

8

这只是一种替代方案。根据 LPUSH 的官方文档,它返回推送操作后列表的长度。您可以设置一个阈值长度,如k(在您的情况下,k > 10),并在返回的长度大于k时调用LTRIM。示例伪代码如下:

len = LPUSH mylist xxx 
if len > k:   
  LTRIM mylist 0 9
LRANGE mylist 0 9

相比于随机方法,它更加可控。更大的 k 会减少 LTRIM 的使用,但会增加内存开销。你可以根据你调用 LTRIM 的频率来调整 k ,因为调用额外命令的代价更高。


这是一个非常聪明的实施,很棒的建议! - undefined

0

调用LTRIM <list-name> -1 -10之后再执行LPUSH <list-name> <item> 是最简单的答案。很多人已经覆盖了这个问题。

你必须在一个事务中执行这两个操作,或者使用Lua脚本来确保操作是原子的。


为什么要选择Lua脚本? - Aman Agarwal
1
Lua确保操作是原子的。在代码层面上,如果您正在使用Lua进行其他工作,那么与事务相比,使用Lua更简单。 - giridhar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接