2012-01-04 4 views
3

nous avons deux entités utilisateur et rôle. Un utilisateur peut avoir plusieurs rôles, et un seul rôle peut être partagé par de nombreux utilisateurs - relation type m: n. Les rôles sont également dynamiques et nous attendons beaucoup (en millions).Modèle de conception Cassandra pour enregistrement partagé (m: n)

Il est simple de modéliser de telles données dans une base de données relationnelle. Je voudrais savoir à chaque fois que ce serait possible à Cassandra.

Actuellement je vois deux solutions:

A) Utiliser le modèle normalisé et de créer quelque chose de similaire à centre-rejoindre

Créer chaque rôle unique dans CF séparés et stocker dans les clés étrangères d'enregistrement d'utilisateur référencés rôles .

pro: Les rôles ne sont pas répliqués et l'entretien est simple

contra: Afin d'obtenir tous les rôles pour les appels de réseau multiples unique de l'utilisateur sont nécessaires. L'enregistrement d'utilisateur contient seulement FK, les rôles sont stockés utilisant le séparateur aléatoire, dans ce cas chaque rôle pourrait être stocké sur le noeud différent de cassandra.

B) Dénormaliser modèle et reproduire les rôles pour éviter les allers-retours Dans ce scénario enregistrement utilisateur dans tous les rôles cassandra contient de l'utilisateur comme copie.

pro: Il est possible de lire l'utilisateur avec tous les rôles dans une seule requête. Cela garantit des temps de chargement courts. Chaque rôle partagé est copié plusieurs fois - sur chaque utilisateur lié. Chaque rôle partagé est copié plusieurs fois. Maintenir des rôles est très difficile, surtout si nous avons quantité importante de données. Par exemple: un rôle est partagé par 1000 utilisateurs. Les modifications de ce rôle nécessitent une mise à jour sur 1000 enregistrements utilisateur. Pour les ensembles de données très volumineux, ces mises à jour doivent être exécutées en tant que travail asynchrone.

Solutions ci-dessus sont très limitées, meybie Cassandra n'est pas bonne solution pour m: n relations? Connaissez-vous un motif de design cassandra pour un tel problème?

Merci, Maciej

Répondre

2

La façon dont vous souhaitez concevoir un magasin de données Cassandra est à start with the queries you plan to execute et font donc vous pouvez obtenir toutes les informations dont vous avez besoin à la fois. La dénormalisation est le nom du jeu ici; Si vous ne répliquez pas ces informations de rôle dans chaque noeud d'utilisateur, vous n'allez pas éviter les recherches de disques et les performances de lecture en souffriront. Les jointures n'ont pas de sens; Si vous voulez une base de données relationnelle, utilisez une base de données relationnelle. En un rien de temps, vous allez vous poser de nombreuses questions sur les rôles d'un utilisateur et sur ce qu'il doit faire avec lui. Vous souhaitez donc que les informations de rôle soient dupliquées dans chaque entrée d'utilisateur, probablement à chaque fois. rôle en obtenant sa propre colonne (role-ROLE_KEY => serialized-capability-info au lieu de roles => [serialized array of capability info]). Votre application aura besoin d'un moyen d'itérer sur toutes ces colonnes elle-même.Vous voudrez probablement voir quels sont les utilisateurs dans un rôle, et vous devriez donc probablement stocker toutes les informations utilisateur dont vous aurez besoin pour cette vue dans la famille de colonnes de rôles (bien qu'un sous-ensemble de l'utilisateur complet record fera l'affaire). Lorsque vous exécutez des mises à jour et que vous ajoutez/supprimez des utilisateurs à partir de rôles, vous devez vous assurer de mettre à jour la liste d'utilisateurs du rôle et les rôles de l'utilisateur en même temps. Comme vous utilisez une colonne pour chaque relation, au lieu d'un seul blob en série partagé, cela devrait fonctionner même si vous modifiez deux rôles différents partageant le même utilisateur en même temps: Cassandra peut fusionner les mises à jour, y compris les suppressions .

Si la requête doit être asynchrone, alors faites en sorte que votre application la gère. Rappelez-vous que Cassandra est un magasin de données à cohérence logique et que vous ne devriez pas vous attendre à ce que les mises à jour soient immédiatement visibles de toute façon.

+1

Cassandra peut être finalement cohérent, mais ce n'est pas obligatoire. Une meilleure description est qu'il a une cohérence accordable basée sur le facteur de réplication et votre niveau de cohérence en lecture et écriture ([R + W> Niveau de cohérence vous donne une forte cohérence] (http://wiki.apache.org/cassandra/API#ConsistencyLevel) – psanford

+0

merci pour la bonne réponse! - Je m'attendais à ça. Dans mon cas, le maintien de tels rôles sera douloureux - surtout, quand j'ai besoin de mettre à jour ce rôle qui est partagé par quelques millions d'utilisateurs .... mais je ne vois pas d'autre option aussi bien –

1

Une autre option de nos jours est d'utiliser playORM qui peut faire des jointures pour vous;). Vous décidez simplement comment partitionner vos données. Il utilise Scalabla JQL qui est une simple addition sur JQL comme suit

@NoSqlQuery (name = "findJoinOnNullPartition", query = "PARTITIONS t ('account',: partId) sélectionne t FROM Trade comme t INNER JOIN t.security comme s où s.securityType =: type et t.numShares =: shares ")

Ainsi, nous pouvons enfin normaliser nos données sur un système noSQL et une échelle en même temps. Nous n'avons pas besoin d'abandonner la normalisation qui a certains avantages.

Dean