„Точно веднъж“ е лъжа: проектиране на интеграции за дубликати

Три копия на една и съща плочка за съобщение, сливащи се в една обработена плочка

Някъде във всеки договор за интеграция има изречение от рода на „всяка поръчка ще бъде предадена точно веднъж.“ Това никога не е било вярно. Мрежата се е разделила по средата на заявката и подателят е направил повторен опит; опашката е доставила повторно след срив на консуматора; складов оператор е натиснал бутона за износ два пъти. Дубликатите не са режим на отказ - те са времето навън.

Идемпотентни ключове, избрани внимателно

Решението е старо и невзрачно: всяко съобщение носи ключ, а обработката е без ефект, когато ключът вече е бил видян. Интересните решения са изцяло в избора на ключа.

  • Естествените ключове побеждават генерираните. Синхронизация на поръчки, ключирана по order_id + status, оцелява при повторно генериране на изходящата опашка от подателя; произволен UUID, генериран в момента на изпращане, не оцелява.
  • Обвържете ключа с ефекта, не със съобщението. Ако едно съобщение създава фактура и резервира наличност, това са два ефекта с два ключа - иначе частичен отказ ви оставя невъзможност да повторите безопасно нито едното от двете.
  • Изтривайте ключовете съзнателно. Хранилище за дедупликация, което расте безкрайно, е бомба със закъснител; такова, което изтича твърде рано, връща дубликатите обратно. По подразбиране използваме 3× максималния хоризонт на повторни опити на подателя.

Тестът, който има значение

Всяка интеграция, която доставяме, преминава през това, което вътрешно наричаме теста с двойно докосване: възпроизвеждаме целия вчерашен журнал от съобщения срещу днешната система, два пъти, и сравняваме получените състояния. Ако нещо се е променило при второто преминаване, пайплайнът не е готов.

Това е жесток тест и се проваля постоянно по време на разработка - при времеви маркери, при одитни полета от типа „създадено от“, при брояч на последователности. Всеки провал е място, където повторна доставка в 3 сутринта тихомълком би повредила данните. Далеч по-евтино е да откриете проблема по време на разработката, отколкото в реална експлоатация.