Хранение временной шкалы событий в Redis

Я хотел бы сохранить список событий на временной шкале в Redis. Я имею в виду отсортированный набор с секундами с 1970 года в качестве счета, что позволяет быстро искать и искать диапазон.

Проблема в том, что я хочу, чтобы каждое из этих событий представляло объект с парой ключей (возможно, около 3), поэтому я бы сохранил отсортированный набор идентификаторов, а затем приложение искало бы хэш на основе идентификатора.

Так что разговор будет примерно таким:

> ZRANGEBYSCORE events start end 
1) "16"
2) "17"
> HGETALL events:16
1) "key1"
2) "val1"
...
> HGETALL events:17
...

Есть ли лучший способ организовать или сделать что-то, чтобы приложение не делало отдельный вызов для каждого результата. Можно ли сделать все на стороне сервера redis, чтобы избежать этих накладных расходов? Это даже большая проблема?

PS. Я использую клиент узла, но мой вопрос относится и к другим языкам.


person Adam    schedule 29.12.2011    source источник


Ответы (2)


Очевидное решение — работать по значению, а не по ссылке. Таким образом, ваш zset может хранить сериализованные объекты вместо хранения ссылок на эти объекты. С узлом JSON прост в использовании.

Теперь, если вам нужно сохранить текущую структуру (поскольку, например, некоторые из ваших объектов являются общими для различных наборов zset), вам нужно думать с точки зрения круговых маршрутов, а не команд. Что дорого в Redis, так это цикл туда и обратно, а не выполнение самой команды O(1).

HGETALL не поддерживает переменные параметры (т. е. вы можете получить только один хэш-объект). Но Redis неплохо справляется с конвейерными командами, и это особенно легко сделать из драйвера node_redis из-за асинхронной природы node. Таким образом, в вашем примере вам просто нужно 2 круговых обхода: первый для выполнения ZRANGEBYSCORE, а второй для выполнения всех команд HGETALL (т.е. не дожидайтесь результата первой команды HGETALL перед выдачей второй). Это будет достаточно эффективно.

В текущей версии Redis (2.4) нет возможности исключить второй цикл.

person Didier Spezia    schedule 30.12.2011
comment
Мы используем именно этот подход для чего-то подобного. Кроме того, ветка сценариев Redis должна позволить вам сделать это за одну поездку. - person tddmonkey; 30.12.2011
comment
Не будет ли недостатков в хранении всей этой информации в одном поле? Как хранить csv в поле rdbms? Это просто компромисс для скорости? - person Adam; 30.12.2011
comment
Нет никакого реального недостатка, когда объекты маленькие. Есть недостаток, когда объекты больше, и вы хотите поддерживать частичное обновление, или когда вы хотите поделиться объектами из разных контейнеров. Что касается вашего замечания о csv, все системы баз данных должны сериализовать строки (mysql, postgreSQL, Oracle и т. д.). Большинство из них поддерживают данные переменной длины (с разделителями или префиксами размера). Формат, который они используют, бинарный, оптимизированный, но с точки зрения сложности стоимость сериализации не сильно отличается от той, которую вы могли бы иметь с простой строкой csv. - person Didier Spezia; 30.12.2011
comment
@DidierSpezia Звучит как хорошее решение для меня. Недостаток, о котором я говорил в столбце CSV, основан не на производительности, а на идеальной практике. Хранение нескольких значений (разделенных, например, запятой) в одном поле таблицы не считается лучшей практикой с точки зрения нормализации (помимо производительности). С точки зрения Redis, хранение этих сериализованных объектов таким образом может помешать мне искать набор на основе каких-либо свойств объектов, хотя я еще не уверен, нужно ли мне это делать. - person Adam; 30.12.2011

Вы можете преобразовать объект в строку и сохранить его как строку с помощью JSON.stringify(), а затем получить его с помощью JSON.parse().

person fent    schedule 30.12.2011