web-dev-qa-db-fra.com

Comment créer des ID d'incrémentation automatique dans Cassandra

Nous savons qu'il est facile de créer des ID d'incrémentation automatique dans les bases de données SQL, existe-t-il une bonne solution pour cela dans Cassandra? Les ID doivent correspondre au nom de la clé ou de la colonne.

44
Andy Wan

La création d'une séquence séquentielle globale de nombres n'a pas vraiment de sens dans un système distribué. Utilisez ID .

(Parce qu'il faudrait que tous les participants soient d'accord et acceptent l'évolution de la séquence - sous une implémentation naïve)

34
Luis Matta

Que diriez-vous de ce qui suit, en utilisant les transactions légères de Cassandra

1 - Créer une table d'ID:

CREATE TABLE ids (
  id_name varchar,
  next_id int,
  PRIMARY KEY (id_name)
)

2 - Insérez chaque identifiant avec lequel vous souhaitez utiliser une séquence globale

Par exemple:

INSERT INTO ids (id_name, next_id)
VALUES ('person_id', 1)

3 - Ensuite, lors de l'insertion dans une table où vous souhaitez utiliser une clé auto-incrémentée, procédez comme suit:

3.1 - Obtenez le next_id de la table ids:

SELECT next_id FROM ids WHERE id_name = 'person_id'

Disons que le résultat est next_id = 1

3.2 - Incrémenter next_id, de la manière suivante:

UPDATE ids SET next_id = 2 WHERE id_name = 'person_id' IF next_id = 1

Le résultat devrait ressembler à ceci:

[{[applied]: True}]

S'il a été mis à jour avec succès, OU

[{[applied]: False, next_id: 2}]

Si quelqu'un d'autre l'a déjà mis à jour.

Donc, si vous avez la valeur True, utilisez l'ID '1' - c'est le vôtre. Sinon, incrémentez next_id (ou utilisez simplement le next_id renvoyé) et répétez le processus.

33
AlonL

Il n'y a pas de bonne solution.

  1. Créez une colonne avec un nombre, augmentez le nombre et enregistrez-le dans toutes les répliques avec un identifiant temporaire, lisez toutes les répliques et vérifiez si l'identifiant temporaire est "le vôtre", sinon recommencez .. pas une excellente solution et ne le fera pas échelle.

ou

  1. Créez votre propre service d'identification où vous récupérez votre prochain identifiant. Ce service ne sera exécuté que dans une seule instance et sera un facteur effrayant non évolutif.

Dès que quelque chose va au-delà d'une seule instance, le séquencement des identifiants devient compliqué, du moins si vous voulez qu'il évolue. Cela inclut les bases de données relationnelles.

15
Simon

il existe un type de données de compteur qui peut être utilisé. Considérez l'exemple ci-dessous.

CREATE KEYSPACE counterks WITH REPLICATION =
{ 'class' : 'NetworkTopologyStrategy', 'datacenter1' : 3 };

Créez un tableau pour la colonne de compteur.

CREATE TABLE counterks.page_view_counts
(counter_value counter,
url_name varchar,
page_name varchar,
PRIMARY KEY (url_name, page_name)
);

Chargez les données dans la colonne du compteur.

UPDATE counterks.page_view_counts
SET counter_value = counter_value + 1
WHERE url_name='www.datastax.com' AND page_name='home';

Jetez un oeil à la valeur du compteur.

SELECT * FROM counterks.page_view_counts;

La sortie est:

 url_name         | page_name | counter_value
------------------+-----------+---------------
 www.datastax.com |      home |             1

Augmentez la valeur du compteur.

 UPDATE counterks.page_view_counts
 SET counter_value = counter_value + 2
 WHERE url_name='www.datastax.com' AND page_name='home';

Jetez un oeil à la valeur du compteur.

 url_name         | page_name | counter_value
------------------+-----------+---------------
www.datastax.com |      home |             3  

Reportez-vous à cela pour plus de détails: http://docs.datastax.com/en/cql/3.1/cql/cql_using/use_counter_t.html

5
mateenk

Cette question est assez ancienne mais j'aimerais la compléter avec une autre solution.

Toute solution qui repose sur la synchronisation des nœuds est déraisonnable. Il est à peu près sûr de casser soit en bloquant la génération d'ID soit en créant des ID en double.

Façon MySQL

Vous pouvez reproduire la façon dont cela se fait avec la réplication maître-maître mysql avec le auto_increment_increment et auto_increment_offset paramètres.

Pour le reproduire, vous devez connaître le nombre de nœuds ou le nombre maximal de nœuds attendus et vous devez créer un compteur (non cassandra) (un fichier par exemple) sur chaque nœud.

Chaque fois que vous souhaitez générer un nouveau nombre, vous trouvez la valeur actuelle, ajoutez l'incrément et l'enregistrez. S'il n'existe pas encore, c'est le décalage.

Donc, pour 10 nœuds, vous auriez un incrément de 10 et un décalage de 1 pour le premier nœud, 2 pour le deuxième nœud, etc. Node 1 créerait les ID 1, 11, 21 . Node 2 créerait les ID 2, 21, 22.

Si vous souhaitez que vos ID soient (approximativement) ordonnés entre les nœuds, vous devez conserver un compteur partagé et vous assurer que chaque ID généré est supérieur au compteur partagé. De cette façon, à moins que vos nœuds/centres de données ne soient désynchronisés pendant une longue période, vous ne devriez pas remarquer beaucoup de différence.

Préfixe

Vous pouvez faire essentiellement la même chose en préfixant l'ID (si c'est une solution acceptable) avec le numéro de nœud (ou nom). Et vous n'avez pas besoin de connaître le nombre de nœuds. Node 1 créerait 1_1, 1_2, 1_3. Node 2 créerait 2_1, 2_2, 2_3.

3
Florent

Je pense que mon humble avis s'attend à Cassandra pour fournir un champ d'incrémentation automatique est FAUX

Cassandra est une élégante base de données décentralisée, donc s'attendre à ce qu'elle fournisse un champ d'auto-incrémentation est, taxant et défait l'objectif initial, car cette valeur doit ensuite être maintenue dans un endroit central

Par conséquent, ne faites aucune solution basée sur la base de données pour obtenir un nombre auto-incrémenté

Au lieu de cela, générez l'ID dans le code ou le service de votre application, qui peut continuer à générer des ID uniques aléatoires et l'utiliser pour l'appliquer sur votre modèle de données, de cette façon, l'objectif et les avantages de Cassandra ne seront pas vaincu

2
Basav

Edit: Cette solution n'est pas appropriée. Voir le premier commentaire.

Ma solution:

1 - Créer une table d'ID:

CREATE TABLE ids (
  id_name varchar,
  next_id counter,
  PRIMARY KEY (id_name)
)

2 - Lors de l'insertion dans une table où vous souhaitez utiliser une clé auto-incrémentée, procédez comme suit:

2.1 - Incrémenter le compteur (il sera créé s'il n'existe pas), en utilisant le plus haut niveau de cohérence

UPDATE ids
  SET next_id = next_id + 1
  WHERE id_name = $AUTO_INCREMENTED_ID
  USING CONSISTENCY ALL

2.2 - Obtenez la nouvelle valeur id:

SELECT next_id
  FROM ids
  WHERE id_name = $AUTO_INCREMENTED_ID

2.3 - Insérez la valeur avec l'ID auto-incrémenté

INSERT INTO some_table ($AUTO_INCREMENTED_ID, ...)
  VALUES ($RESULT_FROM_PREVIOUS_QUERY, ...)

Les mots commençant par '$' dans ma réponse sont des espaces réservés explicites (j'espère) ...

Bien sûr, ce n'est pas une méthode recommandée. Utilisez-le uniquement si vous le devez.

2
AlonL

Doivent-ils vraiment être séquentiels, ou avez-vous simplement besoin de compter des nombres beaucoup plus petits qu'un UUID qui sont facilement saisis par une personne?

Si vous avez vraiment besoin de numéros séquentiels, vous devrez effectuer l'une des opérations suivantes.

  • Ayez une table dans cassandra où la clé/id est un champ pour le générateur, et la valeur est un nombre ... faites des mises à jour conditionnelles dans une boucle jusqu'à ce que vous ayez réussi à incrémenter le compte. (Mauvais idée)

  • Ayez un service de générateur qui vous donnera le prochain numéro. Cela ne peut fonctionner que sur un seul système et être un point de défaillance unique, mais en fonction de vos besoins, cela peut être le meilleur.

Alternativement ... Similaire au premier, mais obtenez des lots de 100 ou plus de nombres à la fois, et distribuez-les à l'intérieur de votre processus/thread ... Cela aura moins de conflits, mais aucune garantie d'ordre séquentiel, seulement l'unicité .. Si vous souhaitez uniquement afficher des numéros plus courts et uniques, cela peut être votre meilleur choix.

1
Tracker1