Changer le schéma D'une table DynamoDB: Quelle est la meilleure façon/recommandée?
Quelle est la méthode recommandée par Amazon pour changer le schéma d'une grande table dans une DynamoDB de production?
Imaginez un hypothétique cas où nous avons une personne de table, avec clé de hachage primaire SSN. Ce tableau peut contenir 10 millions d'articles.
maintenant, la nouvelle vient qu'en raison du volume critique de vols d'identité, le gouvernement de ce pays hypothétique a introduit une autre identification personnelle: identificateur personnel Unique, ou UPI.
nous devons ajouter une colonne UPI et changer le schéma de la table personne, de sorte que maintenant la clé de hachage primaire est UPI. nous voulons supporter pendant un certain temps à la fois le système actuel, qui utilise SSN et le nouveau système, qui utilise UPI<!-Il faut donc que ces deux colonnes coexistent dans le tableau des personnes.
Quelle est la façon recommandée par Amazon pour faire ce changement de schéma?
3 réponses
il y a quelques approches, mais d'abord vous devez comprendre que vous ne pouvez pas changer le schéma d'une table existante. Pour obtenir un schéma différent, vous devez créer une nouvelle table. Vous pourrez réutiliser votre table existante, mais le résultat serait le même que si vous avez créé une table différente.
- migration paresseuse vers la même table, sans flux. Chaque fois que vous modifiez une entrée dans la table personne, créez un nouvel élément dans la table personne en utilisant UPI et non SSN valeur pour la touche de hachage, et supprimez L'ancien article saisi à SSN. Cela suppose que L'UPI utilise une gamme de valeurs différente de celle de SSN. Si SSN ressemble à XXX-XX-XXXX, alors tant que UPI a un nombre différent de chiffres que SSN, alors vous n'aurez jamais de chevauchement.
- migration paresseuse vers la même table, en utilisant les flux. Quand les flux deviennent généralement disponibles, vous serez en mesure d'allumer un flux pour votre table de personne. Créer un flux avec le type de vue new_and_old_images stream, et chaque fois que vous détectez un changement à un élément qui ajoute un UPI à une personne existante dans la table personne, créer une fonction Lambda qui supprime la personne keyed à SSN et ajouter une personne avec les mêmes attributs keyed à UPI. Cette approche a des conditions de course qui peuvent être atténuées en ajoutant un attribut Atomic counter-version à l'élément et en conditionnant L'appel DeleteItem à l'attribut version.
- migration préventive (scriptée)vers une table différente, en utilisant des flux. Exécutez un script qui scanne votre table et ajoute un UPI unique à chaque personne-article dans la table personne. Créez un flux sur la table personne avec le type de vue new_and_old_images stream et souscrivez une fonction lambda à ce flux qui écrit toutes les nouvelles personnes dans une nouvelle table Person_UPI lorsque la fonction lambda détecte qu'une personne avec un UPI a été changée ou qu'une personne a eu un UPI ajouté. Les Mutations sur la table de base prennent habituellement des centaines de millisecondes pour apparaître dans un flux comme enregistrement de flux, de sorte que vous pouvez faire une echec vers la nouvelle table Person_UPI de votre application. Rejeter les requêtes pendant quelques secondes, pointer votre application sur la table Person_UPI pendant ce temps, et réactiver les requêtes.
les flux DynamoDB nous permettent de migrer les tables sans aucun temps d'arrêt. J'ai fait cela avec beaucoup d'efficacité, et les étapes que j'ai suivies sont:
- créer une nouvelle table (appelons cette nouvelle table), avec la structure clé désirée, LSIs, GSIs.
- activer les flux DynamoDB sur la table d'origine
- associer un Lambda au Stream, ce qui pousse le record dans NewTable. (Cette Lambda doit couper le drapeau de migration en pas 5)
- [Facultatif] créer un GSI sur la table d'origine pour accélérer la numérisation des objets. Assurez-vous que ce GSI n'a que les attributs: clé primaire, et migré (voir L'Étape 5).
scannez le GSI créé à l'étape précédente (ou la table entière) et utilisez le filtre suivant:
FilterExpression = " attribut_not_exists (Migrated)"
mettre à jour chaque élément de la table avec un indicateur migrate (i.e.: "Migrated": {"S": "0"}, qui envoie il vers les flux DynamoDB (en utilisant L'API UpdateItem, pour s'assurer qu'aucune perte de données ne se produit).
NOTE: Vous pouvez augmenter unités de capacité d'écriture sur la table pendant les mises à jour.
- la Lambda va ramasser tous les articles, couper le drapeau migré et le pousser dans NewTable.
- une fois que tous les éléments ont été migrés, repoints le code à la nouvelle table
- supprimer la table d'origine, et la fonction Lambda une fois que tout est heureux bon.
Suivant ces étapes pour vous assurer d'avoir aucune perte de données et aucun temps d'arrêt.
j'ai documenté cela sur mon blog, avec le code pour aider: https://www.abhayachauhan.com/2018/01/dynamodb-changing-table-schema/
J'utilise une variante de la troisième approche D'Alexander. Encore une fois, vous créez une nouvelle table qui sera mise à jour au fur et à mesure que l'ancienne table sera mise à jour. La différence est que vous utilisez du code dans le service existant pour écrire aux deux tables pendant que vous êtes en transition au lieu d'utiliser une fonction lambda. Vous pouvez avoir le code de persistance personnalisé que vous ne voulez pas reproduire dans une fonction lambda temporaire et il est probable que vous aurez à écrire le code de service pour cette nouvelle table de toute façon. En fonction de votre architecture, vous pouvez même être en mesure de passer à la nouvelle table sans temps d'arrêt.
cependant, la partie agréable à propos de l'utilisation d'une fonction lambda est que toute charge introduite par des Écritures supplémentaires à la nouvelle table serait sur la lambda, pas le service.