3

经营目标

我正在创建一个依赖于一些时间序列的仪表板,我将使用 Redis 来实现它。我是使用 Redis 的新手,我正在尝试使用 Redis-Streams 来计算流中的元素。

XADD conversation:9:chat_messages * id 2583 user_type Bot
XADD conversation:9:chat_messages * id 732016 user_type User
XADD conversation:9:chat_messages * id 732017 user_type Staff
XRANGE conversation:9:chat_messages - +

我知道我可以使用 XLEN 命令获取元素的总数,如下所示:

XLEN conversation:9:chat_messages

但我也想知道一个时期的元素,例如:

XLEN conversation:9:chat_messages 1579551316273 1579551321872

我知道我可以使用 LUA 来计算这些元素,但我想要一些真正快速的方法来实现这一点,而且我知道使用 Redis 标记将是最快的方法。

有没有办法通过直接的 Redis 命令来实现这一点?还是我必须编写一个 Lua 脚本才能做到这一点?

附加信息

我受 AWS 的 ElastiCache 限制只能使用 Redis 5.0.6,我无法安装其他模块,例如RedisTimeSeries模块。我想使用该模块,但目前不可能。

4

2 回答 2

3

虽然 Redis Stream 数据结构不支持这一点,但您可以在它旁边使用一个 Sorted Set 来跟踪消息范围。

基本上,对于您从中获得的每个消息 ID XADD- 例如“1579551316273-0” - 您需要执行ZADD conversation:9:ids 0 1579551316273-0. 然后,您可以使用ZLEXCOUNT来获取范围的“长度”。

于 2020-01-21T16:16:48.420 回答
1

抱歉,没有命令方式来实现这一点。

Redis Streams 的最佳选择是使用 Lua 脚本。如果存在命令,您将得到 O(N),其中 N 是要计算的元素数,而不是 O(log N)。

local T = redis.call('XRANGE', KEYS[1], ARGV[1], ARGV[2])
local count = 0
for _ in pairs(T) do count = count + 1 end
return count

请注意 O(N) 和 O(log(N)) 之间的差异对于大 N 来说是显着的,但是对于聊天应用程序,如果通过对话跟踪,如果聊天有数百甚至数百个,这不会有那么大的区别数以千计的条目,一旦您计算了总命令时间,包括大部分时间的往返时间。上面的 Lua 脚本删除了网络负载和客户端处理时间。

如果你真的想要 O(log N) 并且你不需要消费者组和其他流功能,你可以切换到排序集。请参阅如何以服务器端时间戳作为分数存储在 Redis 排序集中?如果你想原子地使用 Redis 服务器时间戳。

然后你可以使用O(log(N)) 的ZCOUNT 。

如果您确实需要 Stream 功能,那么您需要将排序集保留为二级索引。

于 2020-01-21T18:14:09.853 回答