Шаблон Cassandra для общей записи (m: n) - PullRequest
3 голосов
/ 04 января 2012

у нас есть две сущности Пользователь и Роль.Один пользователь может иметь несколько ролей, а одна роль может совместно использоваться многими пользователями - типичное отношение m: n.Роли также динамичны, и мы ожидаем большое количество (миллионы).

Просто моделировать такие данные в реляционной БД.Я хотел бы узнать, когда это будет возможно в Кассандре.

В настоящее время я вижу два решения:

A) Используйте нормализованную модель и создайте нечто похожее на inner-join

Создайте каждую отдельную роль в отдельном CFи сохраните в пользовательской записи внешние ключи для ссылочных ролей.

pro: Роли не реплицируются, и обслуживание просто

contra: Для того, чтобыполучить все роли для одного пользователя необходимо несколько сетевых вызовов.Запись пользователя содержит только FK, Роли хранятся с использованием случайного разделителя, в этом случае каждая роль может храниться на другом узле кассандры.

B) Денормализация модели и дублирование ролей во избежание циклических переходов ВВ этом сценарии запись пользователя в cassandra содержит все роли пользователя в качестве копии.

pro: Можно прочитать пользователя со всеми ролями в одном запросе.Это гарантирует короткое время загрузки.

contra: Каждая общая роль копируется несколько раз - для каждого связанного пользователя.Поддерживать роли очень сложно, особенно если у нас большой объем данных.Например: одна роль разделяется 1000 пользователей.Изменения в этой роли требуют обновления 1000 записей пользователя.Для очень больших наборов данных такие обновления должны выполняться как асинхронное задание.

Приведенные выше решения очень ограничены, Мейби Кассандра не является правильным решением для отношений m: n?Знаете ли вы какой-либо шаблон дизайна Кассандры для такой проблемы?

Спасибо, Maciej

Ответы [ 2 ]

2 голосов
/ 05 января 2012

Чтобы спроектировать хранилище данных в Cassandra, вам нужно начать с запросов, которые вы планируете выполнить , и сделать так, чтобы вы могли получить всю необходимую вам информацию сразу. Денормализация это название игры здесь; если вы не реплицируете эту информацию о роли в каждом пользовательском узле, вы не будете избегать поиска диска, и ваша производительность чтения снизится. Объединения не имеют смысла; если вам нужна реляционная база данных, используйте реляционную базу данных.

По-видимому, вы будете задавать много вопросов о том, какие роли имеют пользователи и что им следует делать с ними, поэтому вы определенно хотите, чтобы информация о ролях дублировалась в каждой записи пользователя - возможно, с каждой ролью. получить свой собственный столбец (role-ROLE_KEY => serialized-capability-info вместо roles => [serialized array of capability info]). Вашему приложению потребуется какой-то способ перебора всех этих столбцов.

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

Когда вы запускаете обновления и добавляете / удаляете пользователей из ролей, вам необходимо убедиться, что вы одновременно обновляете как список пользователей, так и роли пользователей. Поскольку для каждого отношения используется столбец, а не один общий сериализованный большой двоичный объект, это должно работать, даже если вы редактируете две разные роли, которые совместно используют одного и того же пользователя: Cassandra может объединять обновления, включая удаления .

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

1 голос
/ 05 сентября 2012

Еще один вариант в эти дни - использовать playORM, который может делать соединения для вас;).Вы просто решаете, как разделить ваши данные.Он использует Scalabla JQL, который является простым дополнением к JQL следующим образом:

@ NoSqlQuery (name = "findJoinOnNullPartition", query = "PARTITIONS t ('account',: partId) выберите t ОТ ТОРГОВЛИ как t ВНУТРЕННЕЕ СОЕДИНЕНИЕ.security как s, где s.securityType =: type и t.numShares =: shares ")

Итак, мы можем наконец-то нормализовать наши данные в системе noSQL и одновременно масштабировать.Нам не нужно отказываться от нормализации, которая имеет определенные преимущества.

Дин

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...