Redis: Как мне посчитать элементы в потоке в определенном диапазоне? - PullRequest
2 голосов
/ 21 января 2020

Цель бизнеса

Я создаю панель управления, которая будет зависеть от некоторых временных рядов, и буду использовать 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 ]

2 голосов
/ 21 января 2020

Хотя структура данных Redis Stream не поддерживает это, вы можете использовать Сортированный набор рядом с ним для отслеживания диапазонов сообщений.

В основном, для каждого идентификатора сообщения, который вы получаете от XADD - например, «1579551316273-0» - нужно сделать ZADD conversation:9:ids 0 1579551316273-0. Затем вы можете использовать ZLEXCOUNT, чтобы получить «длину» диапазона.

1 голос
/ 21 января 2020

Извините, команд для этого не существует.

Лучшим вариантом для 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 атомарно.

Затем вы можете использовать ZCOUNT , что равно O (log (N)).

Если вам нужны функции Stream, вам нужно будет сохранить отсортированный набор как вторичный индекс.

...