A pontosan egyszer egy hazugság: integrációk tervezése duplikátumokra

Ugyanazon üzenetcsempe három példánya egyetlen feldolgozott csempébe fut össze

Minden integrációs szerződésben van valahol egy olyan mondat, hogy „minden megrendelés pontosan egyszer kerül átvitelre”. Ez még soha nem volt igaz. A hálózat kérés közben szétvált, és a küldő újrapróbálkozott; a sor újraküldött egy fogyasztói összeomlás után; egy raktári operátor kétszer nyomta meg az exportgombot. A duplikátumok nem hibamód - ezek időjárás.

Idempotenciakulcsok, gondosan megválasztva

A megoldás régi és nem túl látványos: minden üzenet hordoz egy kulcsot, és a feldolgozás nem történik meg (no-op), ha a kulcsot már láttuk. Az érdekes döntések mind a kulcs kiválasztásában rejlenek.

  • A természetes kulcsok jobbak a generáltaknál. Egy order_id + status alapján kulcsolt megrendelés-szinkronizálás túléli, ha a küldő újragenerálja a kimenő postaládáját; egy küldéskor generált véletlen UUID nem.
  • A kulcsot a hatáshoz rendelje, ne az üzenethez. Ha egy üzenet számlát hoz létre és készletet könyvel, ez két hatás, két kulccsal - különben egy részleges hiba esetén egyiket sem tudja biztonságosan újrapróbálni.
  • Tudatosan járjon le a kulcsoknak. Egy örökké növekvő deduplikációs tár időzített bomba; ha túl hamar jár le, az visszahozza a duplikátumokat. Alapértelmezésként a küldő maximális újrapróbálkozási horizontjának 3×-osát használjuk.

A teszt, ami számít

Minden általunk szállított integráció átmegy azon, amit belsőleg double-tap tesztnek nevezünk: a tegnapi teljes üzenetnaplót kétszer visszajátsszuk a mai rendszeren, és összehasonlítjuk a kapott állapotot. Ha a második lefutás során bármi megváltozott, az adatfolyamat még nincs kész.

Ez egy kíméletlen teszt, és a fejlesztés során folyamatosan elbukik - időbélyegeken, „létrehozta” audit mezőkön, sorszámlálókon. Minden bukás egy olyan pont, ahol egy hajnali 3 órás újraküldés csendben megrongálta volna az adatokat. Sokkal olcsóbb ezt a fejlesztés során elkapni, mint az éles üzemben.