如何计算与模式匹配的键数?

100

我该如何找到所有具有匹配模式的键的计数。

例如,有两个键abc:random-text-1abc:random-text-2。这里的共同模式是abc:。所以,在这里计数为2。

在redis中,我该怎么做?


1
在生产环境中计算Redis键是一个坏主意,永远不要这样做。 - Amin Shojaei
5个回答

88

这里

eval "return #redis.pcall('keys', 'abc:*')" 0

虽然不是O(1),但至少计数是在服务器端完成的。


6
请注意,这仍然使用阻塞的“keys”命令,在大型实例上可能会导致性能问题。 - dizzyf
4
2秒内处理60万个密钥,速度足够快。 - Ram
2
这是O(n)的时间复杂度,其中n是键的数量。对于数百万个键来说真的很糟糕! - Amin Shojaei
1
永远不要在生产环境中调用此函数,无论你的数据集有多小! - Anatolii Stepaniuk
4
@AnatoliiStepaniuk 我不知道。每个人都有自己的理由。但是说“绝对不(!!)”是一个绝对的陈述。正确的方法是解释你的推理,并让人们自行决定何时需要选择。(我认为这个回答是在更好的选择出现之前编写的)。 - warvariuc
显示剩余3条评论

82

免责声明 我希望这个旧回答没有损坏任何拥有数百万键的生产系统。 如果你仍然出于某种原因想要在生产中统计redis匹配键的数量,最好使用带有匹配模式的扫描命令。

如果你只是通过redis客户端使用KEYS进行搜索,你将得到所有匹配键的编号列表,对吗?

例如:

KEYS abc:*

会给你

1) abc:random-text-1
2) abc:random-text-2

或者您可以运行以下命令:

./redis-cli KEYS "abc:*" | wc -l

你将会得到2作为输出。


42
如果有数百万个密钥怎么办? - kivagant
4
那是一个老旧的回答。我应该在这里添加一个免责声明。因此,请勿在拥有数百万键的生产环境中使用此方法。最好使用带有MATCH参数的SCAN游标。 - x_maras
3
不应在生产环境中运行此命令,该命令会阻塞所有请求,如果该命令运行时间过长,则所有请求可能会挂起并超时。 - Arpit Agrawal
当键过期时,这样做是否可行?例如,我正在尝试通过存储到Redis来获取活跃用户的数量。该键已经过期。这是否仍会影响生产环境?谢谢。 - JSTR
嘿,如果我们需要选择数据库怎么办? - Pham Hung
显示剩余3条评论

34

通过命令行执行:redis-cli --scan --pattern 'abc:*' | wc -l


1
你的回答很完美,但需要详细解释,例如:你的 Redis 键:127.0.0.1:6379> keys abc* 1) "abc123" 2) "abc456" 3) "abc234"现在尝试访问它:从命令行运行 redis-cli --scan --pattern 'abc*' | wc -l以下是响应:localhost@username~$ redis-cli --scan --pattern 'abc*' | wc -l 3 - Pankaj Chauhan
2
这应该是被接受的答案。需要使用版本>=2.8.0的Redis。 - Clintm
1
我理解的是否正确,所有匹配的记录都会被获取到客户端? - warvariuc

22

考虑到性能,我不建议您使用KEYS命令。

警告:将KEYS命令仅用于需要特别注意的生产环境中。当针对大型数据库执行该命令时,可能会破坏性能。此命令旨在进行调试和特殊操作,例如更改键空间布局。请勿在常规应用程序代码中使用KEYS。如果您要查找子集中的键的方法,请考虑使用集合。

如果您的redis版本> 2.8.0,则建议您考虑使用scan命令。但它依赖于您将要使用的数据类型。

下面是来自redis文档的简单示例:

redis 127.0.0.1:6379> sadd myset 1 2 3 foo foobar feelsgood
(integer) 6
redis 127.0.0.1:6379> sscan myset 0 match f*
1) "0"
2) 1) "foo"
   2) "feelsgood"
   3) "foobar"

4
你如何使用“scan”函数来计算键的数量? - hasen
你可以阅读官方文档:https://redis.io/commands/scan。或者在谷歌上搜索:https://dev59.com/nFwX5IYBdhLWcg3w-DfJ - Joshua
15
好的,谷歌把我带到了这里 :) 如果您能编辑您的答案并包含一个使用 scan 命令计算匹配模式的键数的简单命令将会很有帮助。 - hasen
好的,我接受你的建议。:-) 这样对其他人来说可能也更容易一些。 - Joshua
2
@Joshua,从扫描API来看,似乎无法在一次尝试中找到总计数。 - Viren
1
如果您想使用SCAN计数键,则需要在每次迭代中存储键,并使用您喜欢的方法过滤重复项(SCAN不能保证值仅出现一次),可能使用允许快速查找现有值的数据结构。对于大量键的集合,这将是不切实际的,因为您需要将所有键存储在内存中,直到扫描完成,因此您需要考虑保留二级键作为计数器,您可以在SET/DEL上更新它,或者将数据存储在允许轻松计数的类型中(例如Redis哈希)。 - philraj

16

如果只是一次性的操作,你可以像x_maras所描述的那样使用KEYS,但在代码中不应该使用KEYS,因为每次调用它时,KEYS将扫描整个数据库中的每个键。

如果你需要频繁执行此操作,正如你所写的那样,没有确切的“好”方法,因为扫描每个键始终相当低效(即使使用SCAN,因为它会以更安全的方式执行与KEYS相同的操作)。

然而,如果你提前知道所需的模式,你可以保留一个匹配该模式的每个键的集合。

SET abc:random-text-1 "blah"
SADD patterns:abc abc:randomtext-1

SET abc:random-text-2 "more blah"
SADD patterns:abc abc:randomtext-2

SCARD patterns:abc
// (integer) 2

SORT patterns:abc BY nosort GET *
// 1) "blah"
// 2) "more blah"

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