16

Je développe actuellement une application Azure Table Storage. Dans cette application j'ai une table qui aura relativement peu d'inserts (quelques milliers/jour) et la clé primaire de ces entités sera utilisée dans une autre table, qui aura des milliards de lignes. Par conséquent, je cherche un moyen d'utiliser un entier auto-incrémenté, au lieu de GUID, comme clé primaire dans la petite table (car cela économisera beaucoup de stockage et d'évolutivité des inserts n'est pas vraiment un problème).Auto-incrémentation sur Azure Table Storage

Il y a eu des discussions sur le sujet, par ex. au http://social.msdn.microsoft.com/Forums/en/windowsazure/thread/6b7d1ece-301b-44f1-85ab-eeb274349797.

Cependant, comme les problèmes de simultanéité peuvent être très difficiles à déboguer et à repérer, je suis un peu mal à l'aise avec l'implémentation de ce problème. Ma question est donc s'il y a une impelemntation bien testée de ceci?

+0

Si vous êtes vraiment inquiet, avez-vous une table en SQL azur qui génère les valeurs d'identité? – Andrew

+0

C'est une très bonne suggestion. Cependant, cela me forcerait à installer mon serveur SQL, car Azure SQL Data Services ne prend pas en charge les colonnes d'identité: http://www.shanmcarthur.net/cloud-services/design-strategies-for-Azure-and-SDS . – Yrlec

Répondre

4

Je ne l'ai pas mis en œuvre ce encore, mais je travaille là-dessus ...

Vous pouvez semer une file d'attente avec vos prochaines ids à utiliser, puis il suffit de les enlever la file d'attente lorsque vous en avez besoin.

Vous devez conserver une table pour contenir la valeur du plus grand nombre ajouté à la file d'attente. Si vous savez que vous n'utiliserez pas une tonne d'entiers, vous pourriez avoir un travailleur de temps en temps se réveiller et s'assurer que la file d'attente a encore des entiers dedans. Vous pouvez également avoir une file d'attente int utilisée que le travailleur peut vérifier pour garder un œil sur son utilisation.

Vous pourriez également accrocher ce travailleur si la file d'attente était vide lorsque votre code avait besoin d'un identifiant (par hasard) il pourrait interrompre la sieste du travailleur pour créer plus de clés dès que possible.

Si cet appel a échoué, vous auriez besoin d'un moyen de (indiquer au travailleur que vous allez faire le travail pour eux (verrouillage), puis faire les travailleurs travail d'obtenir le prochain id et déverrouiller)

  1. verrouillage
  2. obtenir la dernière clé créée à partir de la table
  3. incrément et enregistrer
  4. déverrouiller

puis utilisez la nouvelle valeur.

+1

Mais comment une file d'attente garantit-elle que les ID en double ne sont pas créés? Ce que je peux comprendre de http://download.microsoft.com/download/5/2/D/52D36345-BB08-4518-A024-0AA24D47BD12/Windows%20Azure%20Queue%20-%20Dec%202008.docx est qu'un message est à nouveau ajouté à la file d'attente si un processus de travail échoue lors du traitement du message de la file d'attente. Vous devez donc rendre le travail sur le rôle de travailleur idempotent. Si le même message (c'est-à-dire le même ID) est utilisé par deux rôles de travail différents, je ne vois pas comment vous pouvez rendre cet idempotent. – Yrlec

+2

Si vous n'avez qu'un seul woker en train de créer l'ID, les dups seront placés dans la file d'attente. Lorsque vous sortez les identifiants de la file d'attente, récupérez le message, puis supprimez le message avant d'utiliser le contenu du message (id). Cela devrait garantir qu'aucun ID n'est utilisé plus d'une fois. On dirait que dans le pire des cas, il se peut que vous perdiez une clé, mais votre unicité devrait toujours être bonne. –

+0

La deuxième phrase ci-dessus devrait être: "Si vous n'avez qu'un seul woker en train de créer l'ID, alors les dups ne seront pas mis dans la file d'attente ..." –

3

Si vous avez vraiment besoin d'éviter les guids, avez-vous envisagé d'utiliser quelque chose en fonction de la date/heure, puis de tirer parti des clés de partition pour minimiser le risque de concurrence. Votre clé de partition peut être par utilisateur, année, mois, jour, heure, etc. et la clé de ligne peut être le reste du datetime à un temps suffisamment petit pour contrôler la simultanéité.

Bien sûr vous devez vous demander, au prix de la date dans Azure, si éviter un Guid vaut vraiment la peine de tout cet effort supplémentaire (en supposant qu'un Guid fonctionnera juste).

4

La solution que je trouve qui empêche ids en double et vous permet de autoIncrement il est à

  1. lock (lease) a blob et laisser cet acte comme une porte logique.

  2. Puis lisez la valeur.

  3. Ecrire la valeur incrémentée

  4. Libérer le bail

  5. Utilisez la valeur dans votre app/Table

Ensuite, si votre rôle de travailleur devait tomber en panne au cours de ce processus, puis vous n'auriez qu'un ID manquant dans votre magasin. À mon humble avis, c'est mieux que les doublons.

Voici une code sample and more information sur cette approche de Steve Marx

10

Pour tous ceux qui trouveront à la recherche, il y a une meilleure solution. Minimal time for table lock is 15 seconds - c'est horrible. Ne l'utilisez pas si vous voulez créer une solution réellement évolutive. Utilisez Etag!

Créez une entité dans la table pour l'ID (vous pouvez même le nommer comme ID ou autre).

1) Lisez-le.

2) Incrément.

3) InsertOrUpdate AVECETag spécifié (à partir de la requête lue).

Si la dernière opération (InsertOrUpdate) réussit, alors vous avez un nouvel ID unique, incrémenté automatiquement. En cas d'échec (exception avec HttpStatusCode == 412), cela signifie que certains autres clients l'ont modifié. Donc, répétez encore 1,2 et 3. L'heure habituelle pour Read+InsertOrUpdate est inférieure à 200ms. Mon utilitaire de test with source on github.

+0

Excellente idée. – PilotBob

+0

qu'en est-il de l'utilisation des EGT pour garantir les opérations atomiques, lire et incrémenter? Est-ce une façon viable de le faire? https://docs.microsoft.com/fr-fr/azure/storage/storage-table-design-guide#entity-group-transactions –

Questions connexes