web-dev-qa-db-fra.com

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 modifier le schéma d'une grande table dans un DynamoDB de production?

Imaginez un hypothétique cas où nous avons une table Person, avec une clé de hachage principale 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: Unique Personal Identifier, ou UPI.

Nous devons ajouter une colonne UPI et changer le schéma de la table Person, de sorte que maintenant la clé de hachage principale est UPI. Nous voulons prendre en charge pendant un certain temps à la fois le système actuel , qui utilise SSN et le nouveau système, qui utilise UPI, nous avons donc besoin que ces deux colonnes coexistent dans la table Person.

Quelle est la méthode recommandée par Amazon pour effectuer ce changement de schéma?

32
Dimitre Novatchev

Il existe plusieurs approches, mais vous devez d'abord comprendre que vous ne pouvez pas modifier le schéma d'une table existante. Pour obtenir un schéma différent, vous devez créer une nouvelle table. Vous pourrez peut-être réutiliser votre table existante, mais le résultat serait le même que si vous créiez une table différente.

  1. Migration paresseuse vers la même table, sans Streams. Chaque fois que vous modifiez une entrée dans la table Person, créez un nouvel élément dans la table Person en utilisant UPI et non SSN comme valeur pour la clé de hachage, et supprimez l'ancien élément saisi au SSN. Cela suppose que UPI tire d'une plage de valeurs différente de SSN. Si SSN ressemble à XXX-XX-XXXX, alors tant que UPI a un autre nombre de chiffres que SSN, alors vous n'aurez jamais de chevauchement.
  2. Migration paresseuse vers la même table, à l'aide de Streams. Lorsque les flux deviendront généralement disponibles, vous pourrez activer un flux pour votre table Personne. Créez un flux avec le type d'affichage de flux NEW_AND_OLD_IMAGES et chaque fois que vous détectez une modification d'un élément qui ajoute un UPI à une personne existante dans la table Person, créez une fonction Lambda qui supprime la personne saisie sur SSN et ajoutez une personne avec les mêmes attributs saisis sur UPI. Cette approche a des conditions de concurrence qui peuvent être atténuées en ajoutant un attribut atomique de contre-version à l'élément et en conditionnant l'appel DeleteItem sur l'attribut version.
  3. Migration préemptive (scriptée) vers une autre table, à l'aide de Streams. Exécutez un script qui analyse votre table et ajoute un UPI unique à chaque élément Person de la table Person. Créez un flux sur la table Person avec le type de vue de flux NEW_AND_OLD_IMAGES et abonnez-vous à une fonction lambda 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é modifiée ou lorsqu'une personne avait un UPI ajouté. Les mutations sur la table de base mettent généralement des centaines de millisecondes à apparaître dans un flux en tant qu'enregistrements de flux, vous pouvez donc effectuer un basculement à chaud vers la nouvelle table Person_UPI de votre application. Rejetez les demandes pendant quelques secondes, dirigez votre application vers Person_UPI pendant cette période et réactivez les demandes.
21

Les flux DynamoDB nous permettent de migrer des tables sans aucun temps d'arrêt. J'ai fait cela de manière très efficace, et les étapes que j'ai suivies sont les suivantes:

  1. Créez une nouvelle table (appelons cela NewTable), avec la structure de clé souhaitée, LSI, GSI.
  2. Activer les flux DynamoDB sur la table d'origine
  3. Associez une Lambda au flux, ce qui pousse l'enregistrement dans NewTable. (Cette Lambda devrait couper le drapeau de migration à l'étape 5)
  4. [ Facultatif] Créez un GSI sur la table d'origine pour accélérer la numérisation des éléments. Assurez-vous que ce GSI ne possède que des attributs: clé primaire et migré (voir l'étape 5).
  5. Scannez le GSI créé à l'étape précédente (ou la table entière) et utilisez le filtre suivant:

    FilterExpression = "attribute_not_exists (Migré)"

Mettez à jour chaque élément du tableau avec un indicateur de migration (c'est-à-dire: "Migré": {"S": "0"}, qui l'envoie aux flux DynamoDB (à l'aide de l'API UpdateItem, pour éviter toute perte de données).

[~ # ~] note [~ # ~] : Vous souhaiterez peut-être augmenter les unités de capacité d'écriture sur la table pendant les mises à jour.

  1. La Lambda ramassera tous les éléments, coupera le drapeau migré et le poussera dans NewTable.
  2. Une fois que tous les éléments ont été migrés, redirigez le code vers la nouvelle table
  3. Retirez la table d'origine, et la fonction Lambda une fois satisfaite, tout va bien.

En suivant ces étapes, vous devez vous assurer que vous n'avez aucune perte de données et aucun temps d'arrêt.

J'ai documenté cela sur mon blog, avec du code pour aider: https://www.abhayachauhan.com/2018/01/dynamodb-changing-table-schema/

12
Abhaya Chauhan

J'utilise une variante de la troisième approche d'Alexandre. Encore une fois, vous créez une nouvelle table qui sera mise à jour à mesure que l'ancienne table est mise à jour. La différence est que vous utilisez du code dans le service existant pour écrire dans les deux tables pendant la transition au lieu d'utiliser une fonction lambda. Vous pouvez avoir un code de persistance personnalisé que vous ne souhaitez pas reproduire dans une fonction lambda temporaire et il est probable que vous devrez de toute façon écrire le code de service pour cette nouvelle table. Selon votre architecture, vous pourrez même basculer vers la nouvelle table sans interruption.

Cependant, la partie agréable de l'utilisation d'une fonction lambda est que toute charge introduite par des écritures supplémentaires dans la nouvelle table se fera sur le lambda, pas sur le service.

2
Brian