REL04-BP04 Rendre les opérations de mutation idempotentes - Reliability Pillar

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

REL04-BP04 Rendre les opérations de mutation idempotentes

Un service idempotent garantit que chaque demande est traitée une seule fois, de sorte que la soumission de plusieurs demandes identiques ait le même effet que la soumission d’une seule demande. Il est ainsi plus facile pour un client d’implémenter de nouvelles tentatives sans craindre qu’une demande soit traitée plusieurs fois par erreur. Pour ce faire, les clients peuvent émettre des demandes d’API avec un jeton d’idempotence, qui est utilisé chaque fois que la demande est répétée. Une API de service idempotente utilise le jeton pour renvoyer une réponse identique à la réponse qui a été renvoyée la première fois que la demande a été traitée, même si l’état sous-jacent du système a changé.

Dans un système distribué, il est relativement simple d’effectuer une action au plus une fois (le client soumet une seule demande) ou au moins une fois (le client continue à soumettre des demandes jusqu’à ce qu’il reçoive une confirmation de succès). Il est plus difficile de garantir qu’une action est exécutée exactement une fois, de sorte que la soumission de plusieurs demandes identiques a le même effet qu’une seule demande. En utilisant des jetons d’idempotence dans les API, les services peuvent recevoir une demande de mutation une ou plusieurs fois sans avoir besoin de créer des enregistrements en double ou des effets secondaires.

Résultat escompté : vous disposez d’une approche cohérente, bien documentée et largement adoptée pour garantir l’idempotence sur l’ensemble des composants et services.

Anti-modèles courants :

  • Vous appliquez l’idempotence sans distinction, même lorsque cela n’est pas nécessaire.

  • Vous introduisez une logique trop complexe pour implémenter l’idempotence.

  • Vous utilisez les horodatages comme des clés pour l’idempotence. Cela peut entraîner des inexactitudes en raison d’un décalage d’horloge ou du fait que plusieurs clients utilisent les mêmes horodatages pour appliquer les modifications.

  • Vous stockez des données utiles complètes à des fins d’idempotence. Dans cette approche, vous enregistrez des données utiles complètes pour chaque demande et vous les remplacez à chaque nouvelle demande. Cela peut dégrader les performances et affecter la capacité de mise à l’échelle.

  • Vous générez des clés de manière incohérente entre les services. En l’absence de clés cohérentes, les services peuvent ne pas reconnaître les demandes en double, ce qui peut conduire à des résultats indésirables.

Avantages liés au respect de cette bonne pratique :

  • Capacité de mise à l’échelle accrue : le système peut gérer les nouvelles tentatives et les demandes en double sans avoir à appliquer une logique supplémentaire ni à gérer des états complexes.

  • Fiabilité améliorée : l’idempotence aide les services à traiter plusieurs demandes identiques de manière cohérente, ce qui réduit le risque d’effets secondaires indésirables ou de doublons d’enregistrements. Cela est particulièrement important dans les systèmes distribués, où les défaillances du réseau et les nouvelles tentatives sont communes.

  • Cohérence des données améliorée : étant donné qu’une même demande produit la même réponse, l’idempotence permet de maintenir la cohérence des données dans les systèmes distribués. Cela est essentiel pour maintenir l’intégrité des transactions et des opérations.

  • Gestion des erreurs : les jetons d’idempotence facilitent la gestion des erreurs. Si un client ne reçoit pas de réponse en raison d’un problème, il peut renvoyer la demande en toute sécurité avec le même jeton d’idempotence.

  • Transparence opérationnelle : l’idempotence permet une meilleure surveillance et une meilleure journalisation. Les services peuvent consigner les demandes avec leurs jetons d’idempotence, ce qui facilite le suivi et le débogage des problèmes.

  • Contrat d’API simplifié : il peut simplifier le contrat entre les systèmes côté client et serveur et réduire la crainte d’un traitement erroné des données.

Niveau d’exposition au risque si cette bonne pratique n’est pas respectée : moyen

Directives d’implémentation

Dans un système distribué, il est relativement simple d’effectuer une action au plus une fois (le client soumet une seule demande) ou au moins une fois (le client continue à soumettre des demandes jusqu’à ce que le succès soit confirmé). Toutefois, il est difficile de mettre en œuvre un comportement exactement une fois. Pour ce faire, vos clients doivent générer et fournir un jeton d’idempotence pour chaque demande.

En utilisant des jetons d’idempotence, un service peut faire la distinction entre de nouvelles demandes et des demandes répétées. Lorsqu’un service reçoit une demande contenant un jeton d’idempotence, il vérifie si le jeton a déjà été utilisé. Si le jeton a été utilisé, le service extrait et retourne la réponse stockée. Si le jeton est nouveau, le service traite la demande, stocke la réponse avec le jeton, puis retourne la réponse. Ce mécanisme rend toutes les réponses idempotentes, ce qui améliore la fiabilité et la cohérence du système distribué.

L’idempotence est également un comportement important des architectures axées sur les événements. Ces architectures s’appuient généralement sur une file d’attente de messages telle qu’Amazon SQS, Amazon MQ, Amazon Kinesis Streams ou Amazon Managed Streaming for Apache Kafka (MSK). Dans certaines circonstances, un message qui n’a été publié qu’une seule fois peut être envoyé accidentellement plusieurs fois. Lorsqu’un diffuseur de publication génère et inclut des jetons d’idempotence dans des messages, il demande que le traitement de tout message reçu en double ne donne pas lieu à une action répétée pour le même message. Les consommateurs doivent suivre chaque jeton reçu et ignorer les messages contenant des jetons dupliqués.

Les services et les consommateurs doivent également transmettre le jeton d’idempotence reçu à tous les services en aval qu’il appelle. Chaque service en aval de la chaîne de traitement est de la même manière responsable de la mise en œuvre de l’idempotence afin d’éviter l’effet secondaire consistant à traiter un message plusieurs fois.

Étapes d’implémentation

  1. Identification des opérations idempotentes

    Déterminez quelles opérations nécessitent l’idempotence. Il s’agit généralement des méthodes HTTP POST, PUT et DELETE et des opérations d’insertion, de mise à jour ou de suppression de base de données. Les opérations qui n’entraînent pas de mutation d’état, telles que les requêtes en lecture seule, ne nécessitent généralement pas l’idempotence, sauf si elles ont des effets secondaires.

  2. Utilisation d’identifiants uniques

    Incluez un jeton unique dans chaque demande d’opération idempotente envoyée par l’expéditeur, soit directement dans la demande, soit au sein de ses métadonnées (par exemple, un en-tête HTTP). Cela permet au destinataire de reconnaître et de traiter les demandes ou opérations dupliquées. Les identifiants couramment utilisés pour les jetons incluent les identifiants uniques universels (UUID) et les identifiants KSUID (K-Sortable Unique Identifiers).

  3. Suivi et gestion de l’état

    Tenez à jour l’état de chaque opération ou demande dans votre charge de travail. Pour ce faire, vous pouvez stocker le jeton d’idempotence et l’état correspondant (en attente, terminé ou échec) dans une base de données, un cache ou un autre stockage permanent. Ces informations d’état permettent à la charge de travail d’identifier et de traiter les demandes ou opérations en double.

    Maintenez la cohérence et l’atomicité en utilisant des mécanismes de contrôle de simultanéité appropriés si nécessaire, tels que des verrous, des transactions ou des contrôles de simultanéité optimiste. Cela inclut le processus d’enregistrement du jeton idempotent et d’exécution de toutes les opérations de mutation associées au traitement de la demande. Cela contribue à éviter la survenue de conditions de concurrence et vérifie que les opérations idempotentes se déroulent correctement.

    Supprimez régulièrement les anciens jetons d’idempotence de l’entrepôt de données pour gérer le stockage et les performances. Si votre système de stockage les prend en charge, pensez à utiliser des horodatages d’expiration pour les données (souvent appelés « durée de vie » ou valeurs TTL). La probabilité de réutilisation des jetons d’idempotence diminue avec le temps.

    Les options de stockage AWS courantes généralement utilisées pour le stockage des jetons d’idempotence et de l’état associé incluent :

    • Amazon DynamoDB : DynamoDB est un service de base de données NoSQL qui fournit des performances à faible latence et une haute disponibilité, ce qui le rend parfaitement adapté au stockage de données liées à l’idempotence. Le modèle de données clé-valeur et document de DynamoDB permet de stocker et d’extraire efficacement les jetons d’idempotence et les informations d’état associées. DynamoDB peut également faire expirer automatiquement les jetons d’idempotence si votre application définit une valeur TTL à leur insertion.

    • Amazon ElastiCache : ElastiCache peut stocker des jetons d’idempotence à haut débit, à faible latence et à faible coût. ElastiCache (Redis) et ElastiCache (Memcached) peuvent tous les deux également faire expirer automatiquement les jetons d’idempotence si votre application définit une valeur TTL à leur insertion.

    • Amazon Relational Database Service (RDS) : vous pouvez utiliser Amazon RDS pour stocker les jetons d’idempotence et les informations d’état associées, en particulier si votre application utilise déjà une base de données relationnelle à d’autres fins.

    • Amazon Simple Storage Service (S3) : Amazon S3 est un service de stockage d’objets hautement évolutif et durable qui peut être utilisé pour stocker les jetons d’idempotence et les métadonnées associées. Les capacités de gestion des versions de S3 peuvent être particulièrement utiles pour maintenir l’état des opérations idempotentes. Le choix du service de stockage dépend généralement de facteurs tels que le volume de données liées à l’idempotence, les caractéristiques de performances requises, le besoin de durabilité et de disponibilité, et la manière dont le mécanisme d’idempotence s’intègre dans l’architecture globale de la charge de travail.

  4. Mise en œuvre des opérations idempotentes

    Concevez vos composants d’API et de charge de travail de manière à ce qu’ils soient idempotents. Incorporez des vérifications d’idempotence dans vos composants de charge de travail. Avant de traiter une demande ou d’effectuer une opération, vérifiez si l’identifiant unique a déjà été traité. Si tel est le cas, renvoyez le résultat précédent au lieu de réexécuter l’opération. Par exemple, si un client envoie une demande de création d’utilisateur, vérifiez si un utilisateur possédant le même identifiant unique existe déjà. Si un tel utilisateur existe, ses informations doivent être renvoyées au lieu de créer un nouvel utilisateur. De même, si un consommateur de file d’attente reçoit un message contenant un jeton d’idempotence dupliqué, le consommateur doit ignorer le message.

    Créez des suites de tests complètes qui valident l’idempotence des demandes. Elles doivent couvrir un large éventail de scénarios, tels que des demandes réussies, des demandes ayant échoué et des demandes dupliquées.

    Si votre charge de travail tire parti des fonctions AWS Lambda, envisagez d’utiliser Powertools for AWS Lambda. Powertools for AWS Lambda est une boîte à outils pour développeurs permettant de mettre en œuvre les bonnes pratiques en matière de technologies sans serveur et d’augmenter la rapidité des développeurs dans le cadre de l’utilisation des fonctions AWS Lambda. En particulier, il fournit un utilitaire pour convertir vos fonctions Lambda en opérations idempotentes qu’il est possible de réessayer en toute sécurité.

  5. Communication claire de l’idempotence

    Documentez vos composants d’API et de charge de travail afin de communiquer clairement la nature idempotente des opérations. Cela permet aux clients de comprendre le comportement attendu et de savoir comment interagir de manière fiable avec votre charge de travail.

  6. Surveillance et audit

    Mettez en œuvre des mécanismes de surveillance et d’audit pour détecter tout problème lié à l’idempotence des réponses, tel que des variations de réponse inattendues ou un traitement excessif des demandes dupliquées. Cela peut vous aider à détecter et à étudier tout problème ou comportement inattendu lié à votre charge de travail.

Ressources

Bonnes pratiques associées :

Documents connexes :

Vidéos connexes :

Outils associés :