Redis: как мне подсчитать элементы в потоке в определенном диапазоне?
Деловая цель
Я создаю информационную панель, которая будет зависеть от некоторого временного ряда, и я буду использовать 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. Я бы хотел использовать этот модуль, но в настоящее время это невозможно.
2 ответа
К сожалению, для этого нет команд.
Лучшим вариантом с 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(журнал N), и вам не нужны группы потребителей и другие функции потока. См. Как сохранить в Redis отсортированный набор с отметкой времени на стороне сервера в качестве оценки? если вы хотите использовать временную метку сервера Redis атомарно.
Затем вы можете использовать ZCOUNT, который равен O(log(N)).
Если вам действительно нужны функции Stream, вам нужно будет сохранить отсортированный набор в качестве вторичного индекса.
Хотя структура данных Redis Stream не поддерживает это, вы можете использовать отсортированный набор вместе с ним для отслеживания диапазонов сообщений.
Обычно для каждого идентификатора сообщения, полученного из XADD
- например, "1579551316273-0" - вам нужно сделать ZADD conversation:9:ids 0 1579551316273-0
. Затем вы можете использовать ZLEXCOUNT
чтобы получить "длину" диапазона.