Подтвердить что ты не робот

Поиск в значениях redis db

Я новичок в использовании Redis DB. После прочтения некоторых документов и изучения некоторых примеров в Интернете, а также сканирования stackoverflow.com, я вижу, что Redis работает очень быстро, хорошо масштабируется, но это стоит того, что нам нужно подумать о том, как наши данные будут доступ к ним во время разработки и какие операции они должны будут пройти. Это я могу понять, но я немного запутался в поиске в данных того, что было так легко, как бы медленно, с простым старым SQL. Я мог бы сделать это одним способом с помощью команды KEY, но это операция O (N), а не O (log (N)). Поэтому я потерял бы одно из преимуществ Redis.

Что говорят здесь более опытные коллеги?

Возьмем пример использования: нам нужно хранить личные данные приблизительно. 100 000 человек, и эти данные нужно искать по имени, номер телефона.

Для этого я бы использовал следующие структуры:

1. SET for storing all persons' ids {id1, id2, ...} 
2. HASH for each person to store personal data and name it 
like map:<id> e.g. map:id1{name:<name>, phone:<number>, etc...}

Решение 1:

1. HASH for storing all persons' ids but the key should be the phone number
2. Then with the command KEY 123* all ids could be retrieved who have a phone number 
sarting with 123. On basis of the ids also the other personal data could be retrieved.
3. So forth for each data to be searched for a separate HASH should be created.

Но главный недостаток этого решения заключается в том, что атрибут должен также быть уникальным, так что присвоение номера телефона и идентификаторов в HASH будет однозначна. С другой стороны, время O (N) не является идеальным.

Кроме того, это использует больше места, чем было бы необходимо, а команда KEY ухудшает производительность доступа. (http://redis.io/commands/keys)

Как это сделать правильно? Я мог бы также предположить, что идентификаторы будут проходить в ZSET, а данные, необходимые для поиска, могут быть оценками, но это позволяет работать только с диапазонами, не связанными с серасимами.

Спасибо заранее, привет, Тамас

Резюме ответов: На самом деле оба ответа указывают, что Redis не был предназначен для поиска значений ключей. Если этот случай использования необходим, то необходимо использовать обходные пути, как показано в моем исходном решении или в приведенном ниже решении.

Ниже решение от Eli имеет гораздо лучшую производительность, чем моя оригинальная, поскольку доступ к ключам можно считать постоянным, только список идентификаторов должен быть итерирован через, для доступа это даст время O (const). Эта модель данных также позволяет одному человеку иметь тот же номер телефона, что и кто-то еще и т.д. Также для имен и т.д.... так что возможно 1-n отношения (я бы сказал со старой терминологией ERD).

Недостатком этого решения является то, что он потребляет гораздо больше места, чем мой, и номера телефонов, чьи начальные цифры известны, не удалось найти.

Спасибо за оба ответа.

4b9b3361

Ответ 1

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

Тем не менее, если вы должны сделать это в Redis, вот как бы я это сделал (предполагая, что пользователи могут обмениваться именами и номерами телефонов):

name:some_name -> set([id1, id2, etc...])
name:some_other_name -> set([id3, id4, etc...])

phone:some_phone -> set([id1, id3, etc...])
phone:some_other_phone -> set([id2, id4, etc...])

id1 -> {'name' : 'bob', 'phone' : '123-456-7891', etc...}
id2 -> {'name' : 'alice', 'phone' : '987-456-7891', etc...}

В этом случае мы создаем новый ключ для каждого имени (с префиксом "имя:" ) и каждый номер телефона (префикс "телефон:" ). Каждый ключ указывает на набор идентификаторов, которые имеют всю информацию, которую вы хотите для пользователя. При поиске, например, для телефона, вы будете делать:

HGETALL 'phone:123-456-7891'

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

for id in results:
    HGET id 'name'

Вы стоите здесь O(m), где m - количество пользователей с данным номером телефона, и это будет очень быстрая операция в Redis из-за того, насколько оптимизирована его скорость. В вашем случае это будет излишним, потому что вам, вероятно, не нужно идти так быстро, и вы предпочтете иметь гибкий поиск, но именно так вы это сделаете.

Ответ 2

redis потрясающий, но он не создан для поиска на чем угодно, кроме ключей. Вы просто не можете запрашивать значения без создания дополнительных наборов данных для хранения элементов для облегчения такого запроса, но даже тогда вы не получите истинный поиск, просто больше обслуживания, неэффективное использование памяти, yada, yada...

Этот вопрос уже рассмотрен, у вас есть некоторые чтения: -D

Поиск строк, построение автозаполнения в redis и других интересных вещах...
Как искать строки в redis?

Почему использование MongoDB над redis является разумным при поиске внутри документов... Каков наиболее эффективный механизм работы с документами для хранения тысяч документов среднего размера?