Индексирование с использованием отсортированных наборов Redis

Я хотел бы получить некоторые отзывы и предложения относительно двух подходов, которые яРассмотрим возможность реализации поисковых индексов с использованием отсортированных множеств Redis.

Ситуация и цель

В настоящее время у нас есть несколько таблиц ключ-значение, которые мыхранить в Кассандре, и для которых мы хотели бы иметь индексы. Например, одна таблица будет содержать записи о людях, а таблица Кассандры будет иметь идентификатор в качестве своего первичного ключа и сериализованный объект в качестве значения. Объект будет иметь такие поля, как first_name, last_name, last_updated и другие.

Мы хотим, чтобы мы могли выполнять такие поиски, как "last_name = 'Смит» И имя_> 'Джоэл ","фамилия < 'Ааронсон ","last_name = 'Смит» AND first_name = 'Winston» и так далее. Поиск должен дать идентификаторы совпадений, чтобы мы могли затем извлечь объекты из Кассандры. Я'Я думаю, что вышеупомянутые поиски могут быть выполнены с одним индексом, отсортированным лексикографически по last_name, first_name и last_updated. Если нам нужны поиски с использованием другого порядка (например, "first_name = 'Зевс'") у нас может быть подобный индекс, который позволил бы им (например, first_name, last_updated).

Мы смотрим на использование Redis для этого, потому что мы должны иметь возможность обрабатывать большое количество записей в минуту. Я'Мы ознакомились с некоторыми распространенными способами использования отсортированных наборов Redis и предложили две возможные реализации:

Вариант 1: один отсортированный набор для каждого индекса

Для нашего индекса по last_name, first_name, last_updated мы должны иметь отсортированный набор в Redis по ключевым индексам: people: last_name: first_name: last_updated, который будет содержать строки в формате last_name: first_name: last_updated: id. Например:

кузнец: Joel: 1372761839.444: 0azbjZRHTQ6U8enBw6BJBw

(Для разделителя я мог бы использовать::» скорее, чем ':' или что-то еще, чтобы лучше работать с лексикографическим порядком, но давайтепроигнорируйте это сейчас)

Все элементы будут иметь оценку 0, так что отсортированный набор будет отсортирован лексикографически самими строками. Если я тогда хочу сделать запрос, как "last_name = 'кузнец» И имя_ 'боб»Мне нужно было бы получить все элементы в списке, которые были докузнец: боб.

Насколько я могу судить, у этого подхода есть следующие недостатки:

Нет функции Redis для выбора диапазона на основе значения строки. Эта функция, называемая ZRANGEBYLEX, была предложена Сальваторе Санфилиппо вhttps://github.com/antirez/redis/issues/324 , но не реализовано, поэтому мне пришлось бы находить конечные точки с помощью бинарного поиска и самостоятельно получать диапазон (возможно, с использованием Lua или на уровне приложения с Python, который является языком, который мы используем »используется для доступа к Redis).Если мы хотим включить время жизни для записей индекса, кажется, что самый простой способ сделать это - иметь регулярно запланированную задачу, которая проходит через весь индекс и удаляет просроченные элементы.

Вариант 2: небольшие отсортированные наборы, отсортированные по last_updated

Этот подход будет аналогичным, за исключением того, что у нас будет много меньших отсортированных наборов, каждый из которых будет иметь временное значение, например last_updated для баллов. Например, для одного и того же last_name, first_name, last_updated index у нас будет отсортированный набор для каждой комбинации last_name, first_name. Например, ключом могут быть indexes: people: last_name = smith: first_name = joel, и в нем будет запись для каждого человека, которого мы назвали Джоэл Смит. Каждая запись будет иметь в качестве имени идентификатор, а в качестве значения - значение last_updated. Например.:

значение: 0azbjZRHTQ6U8enBw6BJBw; оценка: 1372761839,444

Основными преимуществами этого являются (а) поиск, когда мы знаем, что все поля, кроме last_updated, будут очень простыми, и (б) реализация времени жизни будет очень легкой, используя ZREMRANGEBYSCORE.

Недостаток, который мне кажется очень большим:

Кажется, что гораздо сложнее управлять и искать таким образом. Например, нам нужно, чтобы индекс отслеживал все его ключи (например, в какой-то момент мы хотим очистить) и делал это иерархически. Поиск, такой как "фамилия < 'кузнец» потребовалось бы сначала просмотреть список всех фамилий, чтобы найти те, которые стоят перед Смитом, затем для каждого из тех, кто просматривает все содержащиеся в нем имена, затем для каждого из тех, кто получает все элементы из своего отсортированного набора. Другими словами, много компонентов для создания и беспокойства.

Завершение

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

Ответы на вопрос(3)

Ваш ответ на вопрос