Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Návrh příjemců zpráv tak, aby zpracování stejné zprávy více než jednou mělo stejný účinek jako zpracování jednou. Systémy zasílání zpráv, které zaručují doručení alespoň jednou, můžou vícekrát doručit stejnou zprávu. Bez odolnosti proti duplicitám může opětovné zpracování zprávy vytvořit duplicitní záznamy, dvakrát účtovat zákazníka nebo mít jiné nežádoucí účinky.
Kontext a problém
Distribuované aplikace si běžně vyměňují úlohy prostřednictvím zprostředkovatele zpráv namísto přímých synchronních volání. Většina zprostředkovatelů, včetně Azure Service Bus, Azure Event Hubs, Apache Kafka a RabbitMQ, poskytuje aspoň jedno doručení. Tato záruka zajišťuje, že zpráva dosáhne příjemce i v případě selhání, ale také to znamená, že zprostředkovatel může doručit stejnou zprávu více než jednou.
Duplicity vznikají z několika zdrojů:
Opakování producenta
Producent odešle zprávu, neobdrží potvrzení kvůli přechodné chybě nebo vypršení časového limitu sítě a zprávu odešle znovu. Zprostředkovatel nyní uchovává dvě kopie, přestože první odeslání bylo úspěšné.
Opětovné doručení po chybějícím potvrzení
Příjemce obdrží a zpracuje zprávu, ale nepotvrdí její přijetí, protože příjemce selže, vyprší zámek nebo se potvrzení ztratí. Zprostředkovatel předpokládá, že zpráva nebyla zpracována a znovu ji doručí.
Selhání příjemce během zpracování
Příjemce dokončí zápis do databáze, ale zhroutí se dříve, než zprávu potvrdí. Když jiná instance převezme znovuzříděnou zprávu, zopakuje zápis.
Doručení právě jednou v rámci distribuovaného systému nelze prakticky zaručit. I brokeři, kteří tvrdí, že poskytují sémantiku exactly-once, zaručují pouze operace, které přímo řídí, například doručování zpráv konzumentům nebo zápis dat zpět do brokeru. Nemohou zaručit externí vedlejší efekty, které klienti vyvolávají v jiných systémech. Trvalým řešením není odstranění duplicitního doručování. Je to, aby to spotřebitel toleroval. Když zkombinujete aspoň jedno doručení s příjemcem, který ignoruje duplicity, dosáhnete efektivního přesně jednoho zpracování.
Řešení
Zajistěte, aby byl konzument idempotentní, vedením záznamů o zpracovaných zprávách a přeskakováním všech zpráv, které už dříve zpracoval. Příjemce zakládá toto rozhodnutí na stabilním identifikátoru, který přetrvá i při opětovném doručení, zkontroluje perzistentní úložiště, aby zjistil, zda již byl tento identifikátor zpracován, a zprávu buď zpracuje, nebo ji zahodí jako duplikát.
Základní tok popisuje následující kroky:
- Přečtěte zprávu a získejte její deduplikační klíč.
- Zkontrolujte úložiště deduplikace pro daný klíč.
- Pokud klíč existuje, považovat zprávu za duplicitní. Potvrďte to a ukončete, přičemž lze volitelně vrátit dříve zaznamenaný výsledek.
- Pokud klíč neexistuje, zpracujte zprávu a zaznamenejte klíč v jedné atomické operaci, potvrďte zprávu.
Volba stabilního klíče odstranění duplicitních dat
Klíč musí logickou zprávu jednoznačně a konzistentně identifikovat při každém opětovném doručení. Použijte identifikátor zprávy přiřazený producentem nebo klíč idempotence na úrovni firmy, který identifikuje konkrétní logickou operaci, nikoli sdílený kontext korelace, který může mít několik zpráv. V Azure Service Bus tato vlastnost slouží k tomuto účelu, MessageId protože jednoznačně identifikuje zprávu a její datovou část. Nepoužívejte CorrelationId jako klíč, protože seskupuje související zprávy, jako je žádost a odpovědi. U událostí, které dodržují specifikaci CloudEvents, sourceid kombinace atributů jednoznačně identifikuje událost a zůstává stabilní v rámci opakování.
Nezakládejte detekci na identifikátorech na úrovni přenosu, které broker při opětovném doručení znovu generuje, ani na hodnotách odvozených od pokusů o doručení, protože se tyto hodnoty mezi duplicitami mění a znemožňují jejich detekci. Vyhněte se také odvozování klíče z nestálých polí, jako jsou například časová razítka příjmu.
Když stejný kanál zpracovává více než jeden nezávislý příjemce, například více odběratelů v architektuře publikování-odběru, každý příjemce oprávněně zpracovává svou vlastní kopii zprávy a potřebuje nezávisle sledovat dokončení jejího zpracování. Pokud tito příjemci sdílejí jedno deduplikační úložiště, určete klíč záznamu podle kombinace identity příjemce a identity zprávy. Úložiště indexované pouze podle identity zprávy umožňuje prvnímu konzumentovi potlačit zpracování u všech ostatních konzumentů.
Rozhodněte se, kam se mají ukládat zpracovávané klíče.
Máte dvě společné možnosti:
Vyhrazená tabulka odstranění duplicitních dat. Příjemce udržuje samostatnou tabulku, někdy označovanou jako doručená pošta, která obsahuje jeden řádek na zpracovaný klíč. Tento přístup udržuje záležitosti deduplikace odděleně od provozních dat a funguje dobře, když mnoho typů zpráv využívá stejný mechanismus.
Samotná obchodní entita. Příjemce uloží klíč do záznamu, který zpráva vytvoří nebo aktualizuje. Tento přístup se vyhne samostatné tabulce, ale páruje odstranění duplicitních dat s tvarem obchodních dat.
Potvrďte značku a vedlejší efekty atomicky.
Postup „nejprve zkontrolovat, poté zpracovat“ obsahuje prostor pro selhání. Pokud příjemce zprávy zprávu zpracuje a poté v samostatném kroku zaznamená klíč, pád mezi těmito dvěma operacemi způsobí, že vedlejší účinky již nastanou, ale klíč nebude zaznamenán, takže při dalším doručení dojde k opětovnému zpracování zprávy.
Toto riziko selhání řešte tak, že značku deduplikace a vedlejší efekty obchodní logiky zapíšete v rámci jedné transakce. Když se obě operace potvrdí společně, nebo se nepotvrdí vůbec, opětovné doručení buď najde potvrzovací značku a přeskočí ji, nebo žádnou značku nenajde, protože transakce byla vrácena zpět, a bezpečně ji znovu zpracuje. Tato transakční varianta je inbox pattern a na straně příjmu představuje protějšek ke Transactional Outbox pattern na straně odesílání.
Ochrana před souběžnými duplicitními položkami
V rámci alespoň jednoho doručení s více konkurenčními příjemci mohou dvě instance přijímat kopie stejné zprávy současně. Obě mohou projít kontrolou existence dříve, než kterákoli z nich potvrdí transakci, takže tato kontrola sama o sobě nezabrání dvojímu zpracování.
Vynucování správnosti v úložišti dat místo logiky aplikace:
Pro klíč odstranění duplicitních dat použijte jedinečné omezení. Obě transakce se pokusí vložit klíč, ale uspěje pouze jedna z nich. Druhé omezení selže a považuje zprávu za duplicitní. Díky tomuto přístupu je databáze jediným arbiterem závodu.
Vyhněte se kontrolám a nastavení ras v mezipamětí. Vzorec, který nejprve zkontroluje klíč a poté jej nastaví ve dvou samostatných operacích, vytváří časové okno, v němž si mohou souběžné opakované pokusy oba nárokovat tentýž klíč. Použijte atomický podmíněný zápis, například vložení, které při konfliktu selže, nebo operaci nastavení pouze v případě, že hodnota ještě neexistuje, aby získání klíče proběhlo v jediném atomickém kroku.
Zpracování vedlejších efektů, které se nemohou připojit k transakci
Některé procesy se nemůžou účastnit databázové transakce příjemce, jako je volání rozhraní API třetí strany nebo zápis do externího úložiště. Pro tyto procesy použijte dvoufázový přístup:
- Před provedením externí akce zaznamenejte klíč ve stavu in-progress.
- Proveďte tento proces.
- Aktualizujte záznam tak, aby se dokončil a uložil výsledek.
Při opětovném doručení vám dokončený záznam umožní přeskočit opakování hovoru. Probíhající záznam signalizuje, že předchozí pokus mohl být částečně dokončený nebo že na tom pracuje jiný uživatel.
Problémy a důležité informace
Při rozhodování o implementaci tohoto modelu zvažte následující body:
Preferujte přirozeně idempotentní operace. Některé operace jsou ze své podstaty idempotentní a nevyžadují žádnou evidenci pro deduplikaci. Upsert založený na obchodním identifikátoru, zápis, který nastavuje absolutní hodnotu namísto přírůstku, nebo požadavek HTTP
PUTna identifikátor prostředku vede ke stejnému výsledku, ať se provede jednou nebo mnohokrát.Někdy můžete operaci učinit přirozeně idempotentní pomocí přenosu stavu neseného událostí, kdy zpráva obsahuje výsledný absolutní stav, například nový stav objednávky, takže ji příjemce zpracuje jako upsert namísto relativní změny.
Tip
Nejprve navrhujte s ohledem na přirozenou idempotenci a techniky deduplikace přidávejte pouze u operací, které nelze přirozeně učinit idempotentními.
Spravujte životní cyklus záznamů deduplikace. Záznamy odstranění duplicitních dat se hromadí, pokud nevypršíte jejich platnost. Zachovejte každý záznam alespoň tak dlouho, dokud může zprostředkovatel znovu doručit původní zprávu. Tato doba závisí na maximálním počtu pokusů o doručení na straně zprostředkovatele, časovém limitu zámku nebo viditelnosti a době životnosti zprávy. Nastavte u deduplikačních záznamů dobu životnosti (TTL), která přesahuje toto časové okno, aby pozdní opětovné doručení stále našlo odpovídající značku. Odstranění záznamů příliš brzy znovu otevře okno pro duplicity. Počítejte se zprávami, které operátor znovu odešle z fronty nedoručených zpráv, protože k opětovnému odeslání může dojít dlouho po uplynutí běžného intervalu opětovného doručení.
Použijte framework pro zasílání zpráv místo toho, abyste deduplikaci vytvářeli ručně. Správně implementovat úložiště pro deduplikaci, atomické potvrzení a čištění záznamů je náchylné k chybám. Architektury založené na zprávách poskytují tento vzor jako integrovanou funkci.
Například NServiceBus odstraňuje duplicity příchozích zpráv podle jejich identifikátoru a poskytuje konfigurovatelnou dobu uchovávání a čištění dat pro deduplikaci. Doručená pošta konzumenta v systému MassTransit eviduje přijaté zprávy podle jejich identifikátoru, aby zajistila zpracování konzumentem právě jednou.
Deduplikace na straně brokeru snižuje, ale neodstraňuje potřebu logiky idempotentního konzumenta. Některé platformy filtrují duplicity v přenosové vrstvě. Azure Service Bus detekce duplicit zahazuje zprávy, které obsahují opakované
MessageIdv rámci nakonfigurovaného časového okna, čímž potlačuje duplicity způsobené opakovanými pokusy producenta o odeslání. Tato funkce funguje na straně odeslání a v rámci ohraničeného okna. Nezabrání tomu, aby příjemce po opětovném doručení zpracoval stejnou zprávu dvakrát, takže stále potřebujete idempotentní logiku na straně příjemce. Považujte funkce platformy za první vrstvu obrany, která snižuje objem duplicit, nikoli za náhradu návrhu.Účet pro řazení zpráv Deduplikace odstraňuje duplicity, ale nezaručuje pořadí. Pokud konzument závisí na pořadí zpracování zpráv, zkombinujte tento vzor s mechanismem pro zajištění pořadí, jako jsou například Azure Service Bus relace zpráv, nebo zahrňte údaje o pořadí či verzi, které konzumentovi umožní odmítnout neaktuální zprávy.
Nástroj pro pozorovatelnost. Vygenerujte klíč odstranění duplicitních dat a identifikátor korelace ve strukturovaných protokolech a sledujte metriku pro zjištěné duplicity. Rostoucí míra duplicit může naznačovat nesprávnou konfiguraci producenta, příliš malé okno potvrzení nebo zámků anebo nefunkční consumery. Pomocí kompletního trasování a korelace můžete sledovat zprávu napříč službami.
Přenášejte idempotenci na následná volání. To, že je jeden konzument idempotentní, nechrání služby, které volá. Když klient v rámci zpracování volá následné služby, předejte dál klíč idempotence, aby každá vrstva mohla odstranit duplicity ve svém vlastním zpracování.
Kdy použít tento vzor
Tento model použijte v těchto případech:
Zprávy používáte od zprostředkovatele, který poskytuje aspoň jedno doručení, což je výchozí hodnota pro většinu zprostředkovatelů.
Při opětovném zpracování zprávy se zobrazí nesprávné výsledky, jako jsou duplicitní finanční transakce, vytvoření duplicitního prostředku nebo opakovaná oznámení.
Tentýž kanál zpracovává více souběžných konzumentů, což zvyšuje pravděpodobnost souběžného duplicitního doručení.
Tento vzor nemusí být vhodný v těchto případech:
Každá operace, kterou konzument provádí, je již přirozeně idempotentní, takže opětovné zpracování je neškodné a evidence deduplikace pouze zvyšuje náklady, aniž by přinášela jakýkoli užitek.
Pracovní zátěž může tolerovat dopady občasného duplicitního zpracování a náklady na úložiště pro deduplikaci převyšují dopad duplicitního zpracování.
Idempotentní zpracování mimo zasílání zpráv
Tento vzor uplatňuje idempotenci u konzumentů zpráv, ale idempotentní zpracování je širším principem spolehlivosti. Každá operace, kterou lze nad stejnou úlohou provést více než jednou, z toho má prospěch. Tento princip zahrnuje transformace ETL (extract, transform, load), které znovu zpracovávají data při opakovaném přehrání, zpracování datových proudů, které pokračuje od kontrolního bodu, naplánované úlohy, které se překrývají nebo restartují, a webhooky nebo koncové body HTTP, které přijímají duplicitní doručení.
V každém případě platí stejná základní technika:
- Určete jednotku práce se stabilním klíčem.
- Poznamenejte si, co jste už zpracovali.
- Přeskočte nebo absorbujte duplicity, aby opakování práce nezměnilo výsledek.
Mechanismy v tomto článku, jako jsou stabilní klíče, atomické značky a jedinečná omezení, se přenesou do těchto kontextů i v případě, že není zapojen žádný zprostředkovatel zpráv.
Návrh úloh
Vyhodnoťte, jak použít model idempotentního příjemce v návrhu úlohy k řešení cílů a principů popsaných v pilířích Azure Well-Architected Frameworku. Následující tabulka obsahuje pokyny, jak tento model podporuje cíle jednotlivých pilířů.
| Pilíř | Jak tento model podporuje cíle pilíře |
|---|---|
| Spolehlivostní rozhodnutí o návrhu pomáhají vaší pracovní zátěži stát se odolná proti poruchám a zajistit, aby se po selhání obnovila do plně funkčního stavu. | Tento model umožňuje úlohě používat aspoň jedno doručení a bezpečné opakování bez poškození dat, což změní duplicitní doručení z rizika správnosti na tolerovanou podmínku. - RE:07 Sebezáchování - Zpracování přechodných chyb |
Pokud tento model představuje kompromisy v rámci pilíře, zvažte je proti cílům ostatních pilířů.
Příklad
Následující příklad ukazuje idempotentního příjemce, který zpracovává objednávky z Azure Service Bus a zachovává stav v Azure Cosmos DB pro NoSQL.
Producent nastaví Service Bus MessageId na identifikátor objednávky na úrovni firmy. Příjemce obdrží zprávy v režimu PeekLock , který znovu odešle zprávu, pokud příjemce nedokončí během doby trvání uzamčení. Kontejner Azure Cosmos DB příjemce se oddíluje podle identifikátoru objednávky (/orderId) a nastavuje dokument id na stejný identifikátor objednávky, takže každá kopie dané objednávky spadá do stejného logického oddílu a samotný záznam objednávky slouží jako značka deduplikace.
Příjemce zpracovává každou zprávu následujícím způsobem:
- Přečtěte si zprávu a použijte ji
MessageIdjako klíč odstranění duplicitních dat. - Vytvořte dokument objednávky tak, aby
idi klíč oddílu byly nastaveny na identifikátor objednávky. - Pokud vytvoření proběhne úspěšně, dokončete zprávu tak, aby ji Service Bus odebrala z fronty.
- Pokud vytvoření selže se stavem HTTP 409 (Konflikt), protože dokument s
idjiž existuje, přečtěte si existující dokument a porovnejte ho s aktuální zprávou. Pokud se shoduje uložený hash požadavku nebo neměnná obchodní pole, považujte zprávu za duplicitní, označte ji za dokončenou a přeskočte její zpracování. Pokud se neshodují, producent mohl znovu použít identifikátor pro jiný obsah nebo se od doby jeho prvního zpracování mohly změnit podrobnosti objednávky, takže zprávu přesuňte do fronty nevyřízených zpráv nebo vyvolejte upozornění, namísto abyste ji tiše zahodili. - Pokud zpracování z přechodného důvodu selže, opusťte zprávu tak, aby ji Service Bus znovu odevzdala, nebo nechte zámek vypršet, aby ji dostal jiný příjemce.
Operace vytvoření je atomická, takže slouží jako kontrola odstranění duplicitních dat i zápisu. Dvě příjemci, kteří obdrží kopie stejné zprávy, nemůžou vytvořit objednávku. Jeden vytvoří vítězství a druhý vrátí konflikt a bezpečně zahodí jeho duplikát.
Pokud je při zpracování potřeba zapsat více než jeden dokument, použijte transakční dávku, která zahrnuje jak deduplikační dokument, tak obchodní dokumenty v rámci stejného klíče oddílu. Protože transakční dávka probíhá v rámci jediného logického oddílu, zvolte takový klíč oddílu, aby jej sdílely všechny dokumenty pro jednu zprávu. Dávka potvrdí všechny dokumenty společně nebo žádné, takže chybové ukončení mezi zpracováním a potvrzením nemůže opustit značku odstranění duplicitních dat a obchodní data mimo synchronizaci. Dávka, která se pokusí vytvořit dokument, který již existuje, vrátí stav 409 (Konflikt), který identifikuje duplikát.
Pokud chcete, aby byl tento příjemce také odolný vůči duplicitním opakovaným pokusům o odeslání, povolte ve frontě funkci detekce duplicit. Detekce duplicit zabraňuje opakovanému odeslání v rámci svého historického okna a idempotentní konzument zpracuje všechny duplicitní zprávy, které se vyskytnou mimo toto okno nebo jsou důsledkem opětovného doručení.
Další krok
- Možnosti asynchronního zasílání zpráv v Azure popisují volby infrastruktury zasílání zpráv, které určují záruky doručení a požadavky na zpracování duplicit.
Související zdroje informací
Vzor Transactional Outbox představuje publikační stranu tohoto vzoru. Spolehlivě publikuje zprávy tak, že je zapíše ve stejné transakci jako obchodní data.
Model opakování umožňuje aplikacím zpracovávat přechodné chyby opakovaným opakováním operací, což umožňuje idempotentní zpracování, protože opakování může způsobit duplicitní doručení.
Odolný návrh Azure Event Hubs a Azure Functions využívá tento vzor pro funkce, které aktivuje služba Azure Event Hubs, včetně technik deduplikace v proudech událostí.
Návrh Azure Functions pro stejný vstup poskytuje pokyny pro vytváření idempotentních funkcí, které tolerují duplicitní vyvolání.