Разработка схемы HBase для наилучшей поддержки конкретных запросов

У меня вопрос, связанный с дизайном схемы HBase. Проблема довольно проста - я храню «уведомления» в hbase, каждое из которых имеет статус («новые», «просмотренные» и «прочитанные»). Вот API, которые мне нужно предоставить:

  • Получить все уведомления для пользователя
  • Получить все «новые» уведомления для пользователя
  • Получить счетчик всех «новых» уведомлений для пользователя
  • Обновить статус для уведомления
  • Обновить статус для всех уведомлений пользователя
  • Получить все «новые» уведомления в базе данных
  • Уведомления должны сканироваться в обратном хронологическом порядке и допускать разбиение на страницы.

У меня есть несколько идей, и я хотел посмотреть, одна из них явно лучшая, или я полностью пропустил хорошую стратегию. Общим для всех трех, я думаю, что иметь одну строку для каждого уведомления и иметь идентификатор пользователя в rowkey - это лучший способ. Чтобы получить хронологический порядок для нумерации страниц, мне также нужна обратная временная метка. Я хотел бы сохранить все уведомления в одной таблице (так что мне не нужно объединять сортировку для вызова «получить все уведомления для пользователя») и не хочу писать пакетные задания для вторичных индексных таблиц (с момента обновления до счет и статус должны быть в реальном времени).

Самый простой способ сделать это: (1) ключ строки - «userId_reverseTimestamp» и фильтрация статуса на стороне клиента.Это кажется наивным, поскольку мы будем отправлять по сети много ненужных данных.

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

Последняя идея, которая у меня возникла, заключалась в том, чтобы (3) иметь два семейства столбцов, одно для статических данных уведомления, а другое в качестве флага для статуса, то есть "s: read" или "s: new" с 's' как cf и статус как квалификатор. Было бы ровно по одному на строку, и я могу использовать MultipleColumnPrefixFilter или SkipFilter с ColumnPrefixFilter против этого cf. Здесь мне тоже пришлось бы удалять и создавать столбцы при изменении статуса, но это должно быть намного легче, чем копирование целых строк. Меня беспокоит только предупреждение в книге HBase о том, что HBase не справляется с «более чем 2 или 3 семействами столбцов» - возможно, если систему необходимо расширить с помощью дополнительных возможностей запросов, стратегия multi-cf не будет масштабироваться. .

Итак, (1) кажется, что это будет иметь слишком много сетевых накладных расходов. (2) кажется, что копирование данных было бы потрачено впустую, а (3) могло вызвать проблемы со слишком большим количеством семейств.Какой фильтр должен обеспечивать лучшую производительность между (2) и (3)? В обоих случаях сканирование будет проверять каждую строку на предмет пользователя, который предположительно имеет в основном уведомления о прочтении, что будет иметь лучшую производительность. Я думаю, что склоняюсь к (3) - есть ли другие варианты (или настройки), которые я пропустил?

10
задан dyross 24 January 2012 в 07:45
поделиться