У меня есть вопрос, связанный с конструкцией схемы HBase. Проблема довольно проста: я храню "уведомления" в hbase, каждый из которых имеет статус ( "новый", "замеченный" и "прочитанный" ). Вот API, который мне нужно предоставить:
- Получить все уведомления для пользователя
- Получить все "новые" уведомления для пользователя
- Получить счет всех "новых" уведомлений для пользователя
- Обновить статус уведомления
- Состояние обновления для всех пользовательских уведомлений
- Получить все "новые" уведомления по базе данных
- Уведомления должны быть сканируемыми в обратном хронологическом порядке и разрешать разбиение на страницы.
У меня есть несколько идей, и я хотел посмотреть, является ли один из них явно лучшим, или если я полностью упустил хорошую стратегию. Общий для всех трех, я думаю, что одна строка за уведомление и наличие идентификатора пользователя в rowkey - это путь. Чтобы получить хронологическое упорядочение для разбивки на страницы, мне также нужно иметь обратную временную метку. Я хотел бы сохранить все примечания в одной таблице (поэтому мне не нужно объединять сортировку для вызова "получить все уведомления для пользователя" ) и не хотите писать пакетные задания для вторичных индексных таблиц (так как обновления до счет и статус должны быть в режиме реального времени).
Простейшим способом сделать это будет (1) ключ строки - "userId_reverseTimestamp" и сделать фильтрацию статуса на стороне клиента. Это кажется наивным, поскольку мы будем отправлять много ненужных данных через сеть.
Следующая возможность состоит в том, чтобы (2) закодировать статус в строке row, так что либо "userId_reverseTimestamp_status", либо затем выполняйте фильтрацию регулярных выражений rowkey при сканировании. Первая проблема, которую я вижу, - это необходимость удалить строку и скопировать данные уведомления в новую строку при изменении статуса (что, предположительно, должно происходить ровно дважды за уведомление). Кроме того, поскольку статус является последней частью строки, для каждого пользователя мы будем сканировать множество дополнительных строк. Это большой успех? Наконец, чтобы изменить статус, мне нужно знать, каков был предыдущий статус (для создания ключа строки), иначе мне нужно будет выполнить другое сканирование.
Последняя идея, которую я имел, состоит в том, чтобы (3) иметь два семейства столбцов: один для статических notif-данных и один как флаг состояния, то есть "s: read" или "s: new" с 's' как cf и статус как определитель. В каждой строке будет ровно одна строка, и я могу сделать MultipleColumnPrefixFilter или SkipFilter w/ColumnPrefixFilter против этого cf. Здесь также мне нужно будет удалить и создать столбцы при изменении статуса, но это должно быть намного легче, чем копировать целые строки. Моя единственная проблема - предупреждение в книге HBase о том, что HBase не преуспевает с "более чем двумя или тремя семействами столбцов" - возможно, если система нуждается в расширении с большим количеством запросов, стратегия multi-cf не будет масштабироваться.
Итак, (1) кажется, что у него слишком много сетевых издержек. (2), похоже, что это потратило бы потраченные расходы на копирование данных и (3) может вызвать проблемы со слишком большим количеством семейств. Между (2) и (3), какой тип фильтра должен обеспечивать лучшую производительность? В обоих случаях сканирование будет смотреть на каждую строку для пользователя, которая, по-видимому, имеет в основном уведомления о чтении, которые будут иметь лучшую производительность. Я думаю, что я склоняюсь к (3) - есть ли другие варианты (или хитрости), которые я пропустил?