Redis:如何计算流中一定范围内的元素?
Redis: How do I count the elements in a stream in a certain range?
商务Objective
我正在创建一个依赖于某些时间序列的仪表板,我将使用 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 模块。我想使用该模块,但目前无法使用。
虽然 Redis Stream 数据结构不支持此功能,但您可以在其旁边使用 Sorted Set 来跟踪消息范围。
基本上,对于您从 XADD
获得的每个消息 ID - 例如“1579551316273-0”——你需要做一个 ZADD conversation:9:ids 0 1579551316273-0
。然后,您可以使用 ZLEXCOUNT
来获取范围的 "length"。
抱歉,没有实现此目的的命令方式。
使用 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
请注意,对于较大的 N,O(N) 和 O(log(N)) 之间的差异很重要,但对于聊天应用程序,如果通过对话进行跟踪,则不会产生太大差异,如果聊天有数百甚至数千个条目,一旦您计算了总命令时间,包括花费大部分时间的往返时间。上面的 Lua 脚本删除了网络负载和客户端处理时间。
如果你真的想要 O(log N) 并且你不需要消费者组和其他流功能,你可以切换到排序集。如果您想自动使用 Redis 服务器时间戳,请参阅 。
然后你可以使用 ZCOUNT 这是 O(log(N)).
如果您确实需要 Stream 功能,那么您需要将排序集保留为二级索引。
商务Objective
我正在创建一个依赖于某些时间序列的仪表板,我将使用 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 模块。我想使用该模块,但目前无法使用。
虽然 Redis Stream 数据结构不支持此功能,但您可以在其旁边使用 Sorted Set 来跟踪消息范围。
基本上,对于您从 XADD
获得的每个消息 ID - 例如“1579551316273-0”——你需要做一个 ZADD conversation:9:ids 0 1579551316273-0
。然后,您可以使用 ZLEXCOUNT
来获取范围的 "length"。
抱歉,没有实现此目的的命令方式。
使用 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
请注意,对于较大的 N,O(N) 和 O(log(N)) 之间的差异很重要,但对于聊天应用程序,如果通过对话进行跟踪,则不会产生太大差异,如果聊天有数百甚至数千个条目,一旦您计算了总命令时间,包括花费大部分时间的往返时间。上面的 Lua 脚本删除了网络负载和客户端处理时间。
如果你真的想要 O(log N) 并且你不需要消费者组和其他流功能,你可以切换到排序集。如果您想自动使用 Redis 服务器时间戳,请参阅
然后你可以使用 ZCOUNT 这是 O(log(N)).
如果您确实需要 Stream 功能,那么您需要将排序集保留为二级索引。