2014-05-04 3 views
0

J'ai un problème avec la fonctionnalité de mon application qui s'intègre à Cassandra. J'essaie de créer un flux de contenu pour mon users. Les utilisateurs peuvent créer des messages qui, à leur tour, ont le champ user_id. J'utilise Redis pour l'ensemble du graphe social et j'utilise des colonnes Cassandra uniquement pour les objets. Dans Redis, l'utilisateur 1 a un ensemble nommé user:1:followers avec tous ses identifiants. Ces identifiants correspondent aux ID Cassandra dans la table users et user_ids dans la table posts.Cassandra/Redis: Façon de créer des flux sans indice secondaire Cassandra 'IN'?

Mon objectif était à l'origine de brancher simplement tous les user_id s de cette Redis mis dans une requête qui utiliserait FROM posts WHERE user_id IN (user_ids here) et saisir tous les postes de l'indice secondaire user_id. Le problème est que Cassandra ne fait pas exprès support l'opérateur IN dans les index secondaires car cet index forcerait Cassandra à rechercher TOUS ses nœuds pour cette valeur. Je ne dispose que de deux options: Soit créer une liste Redis de user:1:follow_feed pour les ID poste, puis rechercher l'index principal de Cassandra pour ces publications dans une seule requête, ou conserver la façon dont je l'ai maintenant et exécuter une requête individuelle pour chaque user_id dans l'ensemble user:1:follower. Je suis vraiment contre la première option parce que j'ai déjà des tonnes et des tonnes de données graphiques dans Redis, et cette option ajouterait une nouvelle liste pour chaque utilisateur. La deuxième façon est bien pire. Je voudrais mettre une charge de lecture massive sur Cassandra et il faudrait beaucoup de temps pour exécuter des requêtes individuelles pour un ensemble d'identifiants. Je suis coincé entre un rocher et un endroit difficile, autant que je le vois. Est-il possible d'interroger les index secondaires avec plusieurs valeurs? Sinon, existe-t-il un moyen plus efficace de charger ces flux de contenu (RAM et vitesse) par rapport aux options de plusieurs listes Redis ou de plusieurs requêtes Cassandra? Merci d'avance.

Répondre

1

Sans connaître le schéma de la table des postes (et de préférence les autres, aussi), il est vraiment difficile de faire des suggestions utiles. Il n'est pas clair pour moi pourquoi vous devez avoir user_id être un index secondaire, par opposition à votre clé primaire.

En général, il est très utile pour le contenu clé comme les messages de l'utilisateur qui l'a créé, car il vous permet de récupérer très efficacement tous les messages (éventuellement sur une plage donnée, en les triant chronologiquement). Avec Cassandra, si vous trouvez qu'une table peut effectivement répondre à certaines des requêtes que vous voulez effectuer mais pas d'autres, il est généralement préférable de dénormaliser cette table et de créer une autre table avec une structure différente afin de conserver votre requêtes vers une seule partition et un seul noeud CQL.

CREATE TABLE posts (
    user_id int, 
    post_id int, 
    post_text text, 
    PRIMARY KEY (user_id, post_id) 
) WITH CLUSTERING ORDER BY (post_id DESC) 

Ce tableau peut répondre à des questions telles que:

select * from posts where user_id = 1234; 

select * from posts where user_id = 1 and post_id = 53; 

select * from posts where user_id = 1 and post_id > 5321 and post_id < 5400; 

Le regroupement inverse sur post_id est de faire les récupérer les plus récents messages les plus efficaces en plaçant au début de la partition physique dans le sstable. Dans cet exemple, id_utilisateur étant une colonne de partition, signifie que "toutes les lignes cql avec cet id_utilisateur seront hachées sur la même partition, et donc sur les mêmes noeuds physiques, et éventuellement sur les mêmes sstables.Voilà pourquoi il est possible de

  1. récupérer tous les messages avec ce user_id, car ils sont magasin jointive
  2. récupérer une tranche d'entre eux en faisant une requête à distance sur post_id
  3. récupérer un seul poste en fournissant à la fois la partition column (user_id) et la colonne de clustering (post_id)

En effet, ceci devient une hashmap d'une recherche hashmap. La principale mise en garde, cependant, est que lorsque vous utilisez des colonnes de partition et de clustering, vous devez toujours fournir toutes les colonnes de gauche à droite dans votre requête, sans en ignorer aucune. Donc, dans ce cas, cela signifie que vous ne pouvez pas récupérer un message individuel sans connaître l'id_utilisateur auquel appartient le post_id. Cela est adressable dans le code utilisateur (en stockant un mappage inversé et en effectuant la recherche si nécessaire, ou en encodant l'id_utilisateur dans le post_id qui est passé autour de votre application), mais c'est certainement quelque chose à prendre en considération.

+0

Intéressant, donc la clé primaire peut être à la fois le user_id et le post_id? – user3181113

+1

La clé primaire peut être un composite de la clé de partition (le premier élément d'une clause PRIMARY KEY * et * la ou les clés de clustering) (toutes les entrées restantes dans cette clause PRIMARY KEY. –

Questions connexes