← Retour

Construction de fonctions idempotentes

2 oct. 2023 | 6 min lecture

Première vue sur la construction de fonctions idempotentes

idempotency impersonation

Revisitons un thème classique mais important, décrit en détail un blog par Slawomir Walkowski, ingénieur logiciel chez Google Cloud. Cet article se penche sur la création de fonctions idempotentes, essentielles pour renforcer la robustesse de vos systèmes serverless.


Présentation des fonctions Idempotentes

En informatique, l'idempotence garantit qu'une fonction produira des résultats cohérents - peu importe le nombre de fois que vous l'exécutez. Lors de l'exécution d'une fonction plusieurs fois pour un événement spécifique, si le résultat final reste le même, alors nous disons que la fonction est idempotente.

Le cœur des fonctions idempotentes réside dans l'aspect de la répétition. Lorsqu'une fonction échoue, nous pourrions avoir besoin de la réessayer pour garantir un comportement correct. Cependant, le défi apparaît si la ré-exécution génère des résultats ou des effets secondaires indésirables. C'est là que la construction de la fonction pour qu'elle soit idempotente devient salvatrice.

Clarifions cette idée avec un exemple, une simple fonction de traitement de données qui écrit les résultats dans deux systèmes de stockage distincts. Anticipez-vous le problème ici ? Que se passe-t-il si le téléversement échoue dans l'un des stockages ? Comme solution rapide, vous pourriez réessayer la fonction. Elle sauvegardera certainement les données dans le second système de stockage (à condition que le téléversement soit réussi), mais elle dupliquera également l'enregistrement dans le premier système, menant à des incohérences potentielles.

Workflow

Comment contournons-nous cela ? Plongeons plus profondément.


Implémenter votre fonction avec l'Idempotence

Que diriez-vous de transformer une fonction non idempotente en une idempotente ? Prenons un exemple où un document est d'abord ajouté à Cloud Firestore, puis téléversé dans un système de stockage séparé. Si le téléversement vers Cloud Firestore est réussi, mais que le second échoue, réessayer ne fait que doubler le même document dans Cloud Firestore. C'est précisément ce que nous cherchons à éviter.

Enregistrement Dupliqué

Utilisé vos Identifiants d'Événement

Une solution viable à ce dilemme consiste à utiliser l'Identifiant d'Événement - qui identifie de manière unique un événement déclenchant une fonction en arrière-plan. En utilisant l'Identifiant d'Événement comme identifiant de document, et en écrivant le contenu du document dans Cloud Firestore, nous garantissons la fonctionnalité idempotente de notre stockage de données et de nos téléversements. En termes plus simples, une exécution de fonction réessayée n'ajoute pas un nouveau document, mais remplace plutôt l'existant par le même contenu. Ainsi, cela évite la duplication des données ou le travail restant. Pour suivre ce principe, vous pouvez fournir l'Identifiant d'Événement comme votre clé d'idempotence dans certaines API spécifiques (par exemple, Stripe).

Identifiant d'Événement

Gérer les Systèmes Non-idempotents

Maintenant, que se passe-t-il si le système avec lequel vous travaillez ne prend pas en charge l'idempotence ? Prenons l'exemple d'un service de livraison d'e-mails. Une fonction réessayée ici pourrait entraîner des e-mails en double. Pour contrer cela, vous pouvez marquer les événements traités en enregistrant leur Identifiant d'Événement, comme nous l'avons déjà discuté. Cela réduit considérablement la chance d'appels réessayés imprévus à d'autres services. Mais cela repose sur l'unicité et la génération appropriée des identifiants d'événement, vous devez donc avoir confiance dans l'idempotence du service. De plus, cela n'est pas adapté aux opérations où le même événement pourrait nécessiter d'être traité de différentes manières selon les circonstances.

Explorer le Mécanisme de Bail (Lease Mechanism)

Bien que les approches mentionnées ci-dessus éliminent la majorité des appels dupliqués lors des réessais de fonction, il existe une faible chance que des exécutions réessayées en parallèle se produisent plus d'une fois. Utiliser un mécanisme de bail est une bonne pratique dans ce cas. Lorsqu'il est utilisé stratégiquement, ce mécanisme vous permet d'exécuter exclusivement la section non idempotente de la fonction pendant une durée spécifique.

Enregistrement de l'Identifiant d'Événement

Un mécanisme de bail implique d'accorder temporairement à un client un accès exclusif à une ressource ou une opération pour une période spécifiée. Pendant cette période de bail, le client peut effectuer l'opération, et d'autres clients sont empêchés de faire la même opération sur la même ressource.

Le bail a un temps d'expiration. Si l'opération n'est pas terminée dans ce délai, le bail expire, et d'autres clients peuvent acquérir un nouveau bail pour tenter l'opération.

Comment cela aide à l'Idempotence

En utilisant des baux, le système garantit que même si la même opération est demandée plusieurs fois (par exemple, à cause d'une répétition), une seule instance de l'opération sera traitée à la fois. Cela évite les opérations en double.

Le système garde une trace des opérations ayant un bail actif. Cette information peut être utilisée pour déterminer si une nouvelle opération entrante est une répétition d'une opération existante ou une nouvelle opération.

Si un bail expire avant que l'opération ne soit complétée, le système peut le gérer de différentes manières. Il pourrait annuler l'opération, la considérer comme échouée, ou permettre à un autre client de réessayer.

Comment l'implémenter
  • Chaque opération est associée à une clé unique (comme un ID de transaction ou un ID d'opération). Cette clé est utilisée pour acquérir et vérifier le bail.
  • Les informations sur le bail (clé, temps d'expiration, etc.) sont généralement stockées dans une base de données persistante et distribuée, accessible à tous les clients et parties du système.
  • Les clients peuvent renouveler les baux s'ils ont besoin de plus de temps pour compléter l'opération. Le système doit gérer les scénarios où un client ne parvient pas à renouveler un bail en raison de problèmes tels que des pannes ou des échecs de réseau.
  • Le système doit gérer les demandes de bail concurrentes de manière à garantir la cohérence et à prévenir les conditions de course.

Pour résumer

Ainsi, lors de la conception de votre architecture serverless, assurer l'idempotence peut considérablement augmenter la fiabilité de vos configurations. Comme nous l'avons vu, plusieurs méthodes, allant de l'utilisation d'identifiants d'événements à l'opération d'un mécanisme de bail, peuvent aider à atteindre l'idempotence.

Facteur Mécanisme de Bail Identifiant d'Événement comme Identifiant de Document
Fonction Principale Accorde temporairement un accès exclusif à une ressource ou une opération. Utilise un identifiant unique pour chaque événement afin de prévenir le traitement en double du même événement.
Cas d'Usage Idéal pour les opérations longues et étatiques et là où les opérations concurrentes pourraient poser problème. Adapté aux opérations sans état où chaque événement est unique et distinct.
Complexité Plus complexe dans l'implémentation. Nécessite de gérer les renouvellements et expirations de bail. Plus simple à implémenter. Repose sur l'unicité et la génération appropriée des identifiants d'événement.
Gestion de la Concurrence Empêche les opérations concurrentes sur la même ressource en fournissant un accès exclusif. Ne gère pas intrinsèquement la concurrence, mais empêche le traitement en double du même événement.
Flexibilité Plus flexible car il permet aux opérations d'étendre leur temps d'exécution en renouvelant le bail. Moins flexible, car les opérations sont généralement ponctuelles et basées sur l'unicité de l'identifiant d'événement.
Gestion des Risques Risque de verrouillage des ressources si un bail n'est pas correctement libéré ou expire. Risque de traitement en double si les identifiants d'événements ne sont pas correctement gérés ou générés.
Scalabilité Peut être difficile à scaler en raison de la nécessité de gérer les baux sur plusieurs instances. Facilement scalable, car chaque opération est indépendante en fonction de son identifiant d'événement.
Scénarios Idéaux Meilleur pour les scénarios avec potentiel de multiples instances essayant de réaliser la même opération. Meilleur pour les scénarios où les opérations sont idempotentes et peuvent être identifiées par un ID unique.
Dépendance de la Base de Données Nécessite une base de données persistante et distribuée pour gérer les informations de bail. Nécessite une base de données où les identifiants d'événements sont utilisés comme clés pour vérifier l'achèvement de l'opération.

Si vous souhaitez approfondir, vous pouvez consulter :

Initializing...