2010-04-12 4 views
2

У меня есть объект модели пользователя с довольно небольшим количеством полей (свойств, если хотите). Скажите «имя», «фамилия», «город» и «год рождения». Каждый пользователь также получает «уникальный идентификатор».Ищет (и общий запрос) с HBase и/или Cassandra (лучшие практики?)

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

Мое понимание (будет работать для почти любой хранения ключ-значение - первый идет ключ, то значение)

и: 123456789 = serialized_json_object

(«U» в качестве простого префикса для ключей пользователя , 123456789 - «уникальный идентификатор»).

Теперь, думая, что я хочу, чтобы иметь возможность осуществлять поиск по Firstname и LastName, я могу сохранить в:

F: Steve = и: 384734807, и: 2398248764, и: 23276263 п: Alex = и : 12324355, u: 121324334

так что ключ «f» - это префикс для firstnames, а «Steve» - это фактическое имя. Для «u: Steve» мы сохраняем как значение всех идентификаторов пользователя, которые являются «Steve's».

Это делает каждый поиск очень-очень простым. Запрос по нескольким полям (свойствам) - скажем по первому (т. Е. «Стив») и последнему (т. Е. «L: Anything») по-прежнему прост - сначала получите список идентификаторов пользователя из «f: Steve», затем перечислите из «l : Anything ", найти перекрестные идентификаторы пользователей, здесь вы идете.

проблемы (и есть немало):

  1. Сохранение, обновление, удаление пользователя является боль. Это должна быть атомная и последовательная работа. Кроме того, если мы имеем размер ценности, ограниченный некоторым значением, то мы находимся в (потенциальной) проблеме. И на самом деле не ответ здесь. Только листинг списка идентификаторов пользователей? Не слишком здорово.

  2. Какой идентификатор мы хотим добавить в поле поиска. В итоге. Скажите «город». Мы, конечно, можем сделать то же самое: «c: Los Angeles» = ..., «c: Chicago» = ..., но если мы не будем предвидеть все эти «варианты поиска» с самого начала, тогда мы будем иметь чтобы иметь возможность создать какую-то ночную работу или что-то, что нужно для всех существующих записей пользователя, и обновить для них «c: CITY» ... Довольно большая работа!

  3. Проблемы с блокировкой. Пользователь «u: 123» обновляет свое имя «Алекс», а пользователь «u: 456» обновляет свое имя «Алекс». Они оба должны обновить «f: Alex» с их идентификаторами. Это означает, что либо мы перейдем к проблеме перезаписи, либо одно обновление будет ждать другого (и изображения, если их много!).

Каков наилучший способ сделать это? Помните, что я хочу искать по многим полям?

P.S. Пожалуйста, вопрос о хранилищах HBase/Cassandra/NoSQL/Key-Value. Пожалуйста, пожалуйста - никаких советов по использованию MySQL и «читать о» SELECT; и беспокоиться о проблемах масштабирования «позже». Есть причина, по которой я задал МОЙ вопрос именно так, как я. :-)

ответ

4

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

Если ваше хранилище данных не имеет встроенных операций индексирования или атомарного списка, вам нужно будет решить проблемы блокировки, о которых вы упоминаете. Однако индексирование необязательно должно быть синхронным - поддерживать очередь обновленных записей, которые нужно переиндексировать, и у вас есть решение для 3, которое можно повторно использовать для решения проблемы 2.

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

Другим вариантом, который в некоторых случаях является полезным, является использование отдельной системы для индексации - например, вы можете настроить lucene для индексации записей в вашем основном хранилище данных.

+0

Можете ли вы предложить лучший способ реализации описанной функциональности для Cassandra/HBase? Мой «собственный» способ - это только моя догадка, что я хотел бы узнать, каковы лучшие практики здесь. – alexeypro

+0

Все это немного новое для реальных практических практик, но метод, который вы описываете, довольно близок к стандарту. Главное улучшение, которое вам нужно, - использовать любую поддержку, которую ваша выбранная платформа имеет для списков, чтобы вы могли добавлять элементы без загрузки всего списка. С Кассандрой вы, вероятно, будете использовать суперколонну. Если у вас есть хранилище с чистым ключом, такое как memcached, вы можете реализовать списки как значения, но вам также нужно реализовать блокировки и, возможно, очереди. –

1

Я предполагаю, что реализовал бы это как задание MapReduce, которое будет выполняться по расписанию. Каждое слово поиска будет строковым ключом с поиском по UID.

RowKey: UID1
Профиль: Имя: Джо
профиля: LastName: Doe
профиля: ник: DoeMaster

RowKey: UID2
профиля: Имя: Jane
профиль: lastName: Doe
профиль: Ник: SuperBabe

MapReduse индексирует все для поиска свойства и добавить их с искомым словом в строке ключа

RowKey: Джейн
поиска: UID: UID2

RowKey: Doe
поиска: Uid : uid2, uid1

Rowkey: DoeMaster
поиска: UID: UID1

..etc

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

Для удаления пользователей дополнительный атрибут, указывающий состояние пользователя, может использоваться для отфильтровывания их из поиска.

Добавление дополнительного слова поиска не очень сложно, так как его имя, значение которого вы хотите индексировать. вы можете также фильтровать поиск, добавив атрибут типа к вашему ключевому слову/ключевому слову. i.e boston - поиск: тип: город.

Идея состоит в том, чтобы поддерживать свой собственный индекс поиска на основе строки внутри hbase.

 Смежные вопросы

  • Нет связанных вопросов^_^