-
Notifications
You must be signed in to change notification settings - Fork 0
Notes
Répertoire de scénarios de crash ésotériques et (avec un peu de chance) la façon dont on les gère.
Messages croisés entre RM et MW lors d'un recovery au RM ayant planté en plein milieu d'une transaction
- Un RM plante durant une transaction en cours (2PC non-commencé), et perd les données.
- Le RM redémarre, et selon le protocole de redémarrage, demande au MW d'abort la transaction.
- Avant que le message du RM atteigne le MW, le MW envoie une opération quelconque (mettons K) au dit RM.
Résultat: J'avais une grosse explication disant que tout ça était quasiment impossible. En fait, c'est beaucoup plus simplement impossible, parce que le RM ne peut pas recevoir de commandes avant d'avoir fini son protocole de redémarrage. Yay!
Le RM et le MW plantent en même temps en plein milieu d'un 2PC. Mettons que le RM a envoyé oui mais pas reçu de confirmation. Dans ce cas le protocole de redémarrage lui indique de demander au MW quel était le résultat de la transaction. Mais le protocole de redémarrage du MW lui indique de dire quoi faire au RM. Donc ni l'un ni l'autre ne peut avancer sans avoir de réponse de l'autre.
Ici je crois que ce qui va se passer, c'est qu'il va y avoir une exception au moment de l'appel du proxy pour au moins l'un des deux. Il faudrait vérifier si, lorsqu'on est toujours dans une méthode marquée @PostConstruct, le WS peut déjà commencer à recevoir des messages ou s'il doit avoir retourné de cette méthode. Dans les deux cas, ça devient pas mal compliqué après. En fait, selon ce qu'on a vu en fin de semaine, ça semble bloquer indéfiniment. D'autres tests sont à faire.
Mettons que le RM et MW plantent en plein milieu d'un 2PC (encore). Le RM a planté après avoir envoyé oui, et le MW a planté après avoir pris la décision (qui était VRAIE) mais avant d'avoir envoyé cette décision. Le MW revient en premier, et comme il ne peut pas parler au RM, laisse tomber sa partie du protocole de redémarrage (donc n'arrive pas à transmettre la décision). Ensuite, le RM revient. Selon SON protocole de redémarrage, il demande au MW (avec succès) quel était le résultat de la transaction. Or, comme le MW a planté, le TM ne contient pas d'ID pour cette transaction, et donc le résultat retourné est FAUX. (Ou pire, le TM contient l'ID, mais pour une autre transaction pas rapport).
Solution potentielle: lorsque le MW redémarre, il garde en tête les transactions qui n'ont pas été complétées mais qui ont un résultat et indique au TM de ne pas réutiliser ces IDs. Lorsqu'on reçoit un queryTxnResult, on regarde d'abord du côté de ces IDs-là pour voir s'il y a un résultat avant de checker le TM.
Le RM plante après avoir envoyé son vote OUI. Lors du redémarrage, il demande donc au MW ce qui se passe. Or le MW est encore en train d'attendre un aute OUI d'un bonhomme. Donc, il n'y a pas encore de résultat pour la transaction et le MW dit: abort! Mais ensuite l'autre RM finit par répondre et dit oui aussi, donc le MW décide de committer, et on vient donc de perdre des données.
Solutions potentielles:
- Le TM contient un objet indiquant que la transaction est "indéterminée". Le RM ayant planté, voyant cela, attend d'avoir le vrai résultat.
- Le MW doit checker s'il n'y a pas déjà un flag d'abort au TM avant de décider "pour vrai". S'il y en a un, il envoie un abort. Cette solution viole toutefois les conditions de non-trivialité du protocole de consensus parce que tous ont voté OUI mais la décision est quand même NON.
À considérer. La solution la plus simple semble de garder les anciens logs intouchés jusqu'à la toute fin du redémarrage. Donc, si on plante à un moment donné, on recommence à nouveau comme si de rien n'était.