2025 ж. 29 мау.·6 мин

Жүйелер арасындағы оқиғалық интеграция: кезектер мен идемпотенттік

Жүйелер арасындағы оқиғалық интеграция: қандай кезекті таңдау, өңдеуді идемпотентті қылу және қайта жеткізілуге сабырлы қарау керек.

Жүйелер арасындағы оқиғалық интеграция: кезектер мен идемпотенттік

Практикада оқиғалармен қандай қиындықтар болады

Оқиғалар арқылы жүйелерді біріктіру схема бойынша қарапайым көрінеді: бір жүйе бірдеңе жасады да оқиға жіберді, екіншісі алды да өңдеді.

Шындығында жиі пайда болатын жағымсыз жайт — бір ғана оқиға екі рет, тіпті үш рет келіп қалуы мүмкін. Хабарлама кезектері мен таратылған жүйелер үшін бұл қалыпты жағдай.

Қайталану «кімдең жақсы істемеді» дегеннен емес, жүйенің сенімді болуға тырысқанынан шығады. Жіберуші қысқа желі үзілуіне байланысты жеткізу растауын алмауы мүмкін. Брокер қайта жүктелгенде жеткізуді қайталауы ықтимал. Тұтынушы өңдеуден кейін құлап, нәтижесін бекітпей қалса, қайта іске қосылғанда хабарламаны тағы көріп қалуы мүмкін. Сондықтан кепілдеме көбінесе «кем дегенде бір рет жеткіземіз» деп айтылады, «көлемі дәл бір рет» емес.

Мәселе сол, қайталанған оқиға көбіне әрекеттің де қайталануына әкеледі. Ең қауіпті аймақтар — ақша (қосымша ұсталулар немесе қайтарулар), қойма (қордың екі еселенуі), статустар (өтініш екі рет кезеңге ауысуы), хабарламалар (екі бірдей хат немесе SMS).

Жаман интеграция операциялық жұмыста тез байқалады: жүйелер арасындағы сандар сәйкес келмейді, кестелерде қолмен түзетулер пайда болады, қызметкерлер әр операцияны екі рет тексеретін болады, ал тексерулер сағаттар алады. Кейде бұл «өздігінен түзеледі» деп маскировка жасалады, себебі кейін тағы бір оқиға келіп, бөліп түзетеді.

Болжамды интеграция қайталануларды қабылдаудан басталады. Өңдеуді осылай құрады: қайталанған оқиға деректерді бұзбайды. Сол кезде жүйе жеткізу санына қарамастан бірдей жұмыс істейді: әрекет бір рет орындалады немесе қайталанбас жаңару қауіпсіз түрде еленеді, қорытынды күй дұрыс қалады.

Оқиғалар мен сұраулар: қарапайым тілмен айырмашылығы

Сұрау — бір жүйе екіншіден тікелей «Мені қазір жауап бер» деп сұрайды. Мысалы, төлем сервисі тапсырыс сервисіне сұрау жібереді: «Бұл тапсырыс бар ма?» және жауап күтеді.

Оқиға — жүйенің фактіні хабарлауы: «Меніде бірдеңе болды». Мысалы: «Тапсырыс құрылды», «Төлем өтті», «Өтініш статусы өзгерді». Біреу дереу жауап беруге міндетті емес, ал қабылдаушылар бірнеше болуы мүмкін.

Түсінікті салыстырма: сұрау — сұрақпен қоңырау шалуға ұқсайды, оқиға — жалпы чатқа хабарлама салуға. Сұрауда лезде жауап маңызды. Оқиғада ақпарат қажетті барлық тарапқа жетуі маңызды.

Оқиғалар күй өзгеретін және бірнеше жүйені қатты байланыстырмай хабарландыру қажет жерлерде тиімді: статустардың өзгерісі, деректер өзгерістері, хабарламалар, аудит.

Оқиғалық схема екі рөлден тұрады. Продюсер (producer) оқиғаны жариялайды — ол «сұрамайды», ол «хабарлайды». Консьюмер (consumer) оқиғаны алып, не істеу керектігін шешеді: өз базасын жаңарту, хабарлама жіберу, есептеу бастау.

Оқиғалар әдетте асинхронды: продюсер барлық консьюмерлердің өңдеуін күтпейді. Ол оқиғаны кезекке жіберіп, жұмысты жалғастырады. Бұл жүктеме мен ақауларға төзімділікті арттырады, бірақ жаңа шындықты қосады: оқиғалар кешігуі, тәртіпсіз келуі және кейде қайта келуі мүмкін.

Хабарламалар кезегі қалай жұмыс істейді және не береді

Хабарламалар кезектері жүйелерді бір-біріне тәуелді ете бермей байланыстырғандықтан пайдалы. Бір жүйе «қазір жаса» деп шақырудың орнына оқиғаны (хабарламаны) кезекке жібереді, екінші жүйе оны дайын болғанда алады.

Кезек буфер сияқты жұмыс істейді. Егер тұтынушы уақытша қолжетімсіз болса (жаңарту, ақау, желі проблемасы), оқиғалар бірден жоғалмай, жиналып күтіп тұрады. Бұл жіберушінің қабылдаушының тоқтауына байланысты құлауы керек емес деген жағдай үшін маңызды.

Жүктеме шарықтауында да кезек құтқарады. Мысалы, таңғы 9:00-де көп қолданушы бір уақытта өтініш жасаса, жіберуші оқиғалар толқынын құрайды. Кезексіз қабылдаушы шектен тыс жүктелуі мүмкін. Кезек арқылы шарықтау біркелкі ағымға айналады: тұтынушы өз темпіне сай өңдейді, қалғаны уақытша сақталады.

Тұтынушы хабарламаны сәтті өңдегенде ол растама (ack) жібереді. Бұл кезекке «әрі қарай өшіруге болады» деген сигнал. Егер ack келмесе (тұтынушы құлаған, ілініп қалған, үлгермеген болса), кезек әдетте хабарламаны қайта жіберуге тырысады. Мұндағы негізгі қорытынды: кезек сенімділікті арттырады, бірақ қайта жеткізулерге дайын болу қажеттілігін жоймайды.

Тағы бір миф — кезек әрдайым мінсіз тәртіп сақтайды. Практикада тәртіп параллель өңдеу, қайта жеткізу немесе таратылған кезектің ерекшеліктері салдарынан бұзылуы мүмкін. Сондықтан өңдеуді дубльдер мен «аздап басқа тәртіпте» келген хабарламаларға төзімді етіп жобалау жақсы.

Жеткізу кепілдіктері және неге қайта жеткізілудер қалыпты

Кезектерде жиі кездесетін кепілдік — «кем дегенде бір рет». Бұл шынайы компромисс: жүйе хабарламаны жоғалтпауға тырысады, кейде оны қайта жеткізу керек болады.

Қайталану жүйенің бұзылуынан емес, нақты әлемнің «шулығы» себебінен пайда болады. Тұтынушы оқиғаны өңдеп, бірақ кезекке растама жіберіп үлгермеген болуы мүмкін. Кезек растама жоқ деп санап, хабарламаны қайта жібереді.

Қайта жеткізілуге жиі себептер: желі таймауттары, тұтынушының қайта қосылуы, кезек немесе қосымшаның ретрайлері, ұзақ өңдеу (көріну уақыты өтіп кетуі), бірнеше сервис нұсқасының бәсекелес өңдеуі.

Неліктен «дәл бір рет» жасамасқа? Себебі мұны істеу үшін ортақ «шынайы дереккөз» қажет, ол не өшірілмей, не бизнес-деректермен бірге атомарлы өзгеруі тиіс. Өңдеу дерекқорға, сыртқы сервистерге, файлдарға немесе екі түрлі транзакцияларға әсер етсе, қай жерде өзгеріс бекітілгенін қатаң бақылау керек. Жүктеме мен ақаулар кезінде бұл тез қымбатқа және күрделіге айналады.

Сондықтан бизнес-оқиғалар үшін әдетте «жоғалтпаймыз, бірақ қайталанулар бар» деген таңдау жасалады. Оддан әрі талаптар тұтынушының кодына өтеді: қайталану қалыпты жағдай болуы керек, ол апат емес.

Идемпотенттік: ол не және қай жерде болуы тиіс

Идемпотенттік — біршама қарапайым нәрсе: бір әрекетті бірнеше рет орындаса да нәтиже өзгермейді және қосымша жанама әсерлер болмайды. Оқиғалар үшін бұл өте маңызды, өйткені қайта жеткізілу жиі кездеседі: ретрайлер, желі үзілістері, тұтынушының қайта іске қосылуы.

Екі идеяны ажыратқан жөн.

Идемпотентті операция — бизнес-әрекет қайталанса да қауіпсіз болатын нәрсе (мысалы, «өтініштің статусын ТӨЛЕНДІ деп қою»).

Идемпотентті оқиға өңдеуші — бірдей оқиғаны қайта алған жағдайда деректерді бұзбайтын және қымбат әрекеттерді (қолма-қол ақша алу, жөнелту, т.б.) екінші рет орындамайтын код.

Неидемпотенттік ең алдымен ақша мен логистикада көрінеді: бір төлем оқиғасын екі рет өңдеп, ақша екі рет алынуы мүмкін; «тапсырыс расталды» оқиғасын қайталап, екі рет жөнелту орын алуы мүмкін; бонустарды қосу өңдеуші «қосу» логикасында болса, қайта есептеліп қосылады.

Көп жағдайда идемпотенттілікті тұтынушы жағында қамтамасыз ету ыңғайлы. Оқиға жариялаушысы сырттағы жүйе болуы мүмкін, ал тұтынушы өз деректеріне және жанама әсерлерге жауапты.

Өңдеушіні тез тексеру:

  • оқиғада бірегей идентификатор бар ма және сіз өңделгенін тіркейсіз бе (event_id);
  • объектіні қажетті күйге келтіресіз бе, яғни «қайтадан қосу» емес, нақты күйге қою;
  • қайтарылмайтын әрекеттер (ақша алу, жөнелту, хат жіберу) бөлек қорғалған ба және оларды қайталанудан қорғайтын механизм бар ма.

Егер бір оқиғаны қайта қабылдау нәтиже өзгертуге әкелмесе, эксплуатация әлдеқайда тыныш болады.

Дубликаттан қорғаудың негізгі әдістері

Идемпотенттік пен дубльдерді аудиттеу
Тұтынушыларды идемпотенттілікке тексеріп, қай жерде қосалқы әрекеттер пайда болатынын анықтаймыз.
Аудит тапсыру

Дубликаттар тіпті жақсы бапталған кезек жағдайында да пайда болады: брокер желі үзілісі, таймаут немесе тұтынушының қайта жүктелуі себебінен хабарламаны қайта жібере алады. Сондықтан жүйелерде көбіне қорғауды тұтынушы жағында ұйымдастыру керек, «қайталанулар болмайды» деген үмітке сүйенбеңіз.

Негіз — оқиғаның бірегей идентификаторы (event_id). Оны әдетте оқиғаны тудыратын жүйе тағайындайды, себебі сол жүйе оқиғаны жасайды және өз аумағында бірегейлікті қамтамасыз ете алады. Егер event_id тұтынушы тарапынан жасалса, сіз тек өзіңіздің қайталануларыңыздан ғана қорғайсыз, сырттан келген қайта жеткізуден емес.

Келесі қадам — өңделген оқиғалар реестрі: дерекқор кестесі, key-value дүкен немесе бөлек коллекция. Принцип бір: әрекет орындамас бұрын event_id көрген ба екеніңізді тексересіз. Егер көрген болса — хабарламаны растап, ештеңе жасамайсыз. Көрмеген болса — жұмысты істеп, өңдеудің фактін жазасыз.

Тұрақты жұмыс істеуі үшін минималды контекст сақтау пайдалы: event_id, алғашқы өңдеу уақыты, статус/нәтиже, объектінің кілті (мысалы, order_id, ticket_id), әрекет нөмірі (егер болса).

Сыртқы жүйелерге шақырулар бөлек тақырып. Егер тұтынушы API арқылы төлем, өтініш немесе пайдаланушы жасаса, идемпотентті кілт керек. Оны сыртқы сұранысқа беріп, қайталанған шақыру екінші объект жасамай, сол нәтижені қайта береді. Көбіне осындай кілт ретінде event_id немесе «оқиға типі + объект id» жұбы пайдаланылады.

Мысалы: «Шот төленді» оқиғасы екі рет келді. Тексерусіз сіз екі рет қолжетімділік бересіз. Өңделген оқиғалар журналымен екінші рет келгенін байқап, әрекетті өткізіп жібересіз, жүйеде дұрыс күй қалады.

Қадамдап: тұтынушыны қайталануларға төзімді ету

Қайта жеткізілу — кезектер өмірінің қалыпты бөлігі. Егер тұтынушы дайын болмаса, бірдей бизнес-операция екі рет орындалуы мүмкін: ақша алынуы, қолжетімділік екі рет берілгені, өтініш екі рет жасалуы. Шешім — қайталануларды тыйу емес, өңдеуді тұрақты ұйымдастыру.

Көп жағдайда жұмыс істейтін 5 қадам

Бастапқыда әр хабарлама бірегей идентификатор таситын келісімге келіңіз. Бұл event_id (UUID) және қажет болса домендік кілт (мысалы, order_id) мен оқиға түрі болуы мүмкін.

Келесі — өңделгенін қайда сақтайтыныңызды таңдау. Бұл сіз сенетін орын болуы керек: әдетте тұтынушы дерекқоры (өңделген оқиғалар кестесі) немесе сол сервиске қолжетімді дүкен.

Одан кейін өңдеуді және нәтижені бекіту бір «бөлінбейтін» әрекет болуы тиіс. Практикалық тәсіл — бір транзакция: (1) event_id бұрын кездеспегенін тексеру, (2) бизнес-өзгерісті орындау, (3) оқиғаның өңделгенін жазу. Сонда қайта келгенде тез әрі қауіпсіз түрде дубль екенін анықтап, аяқтайсыз.

Сосын ретрайлерді солай орнатыңыз, олар көмектесу керек, бүлдіру емес. Қайталанулар саны мен мерзімі шектелсін, ал «улы» хабарламалар бөлек ағынға жіберіліп, шексіз айналуға жіберілмесін.

Ақырында, оқиға схемасын өзгерту ережелерін келісіңіз. Жаңа өрістерді ескі тұтынушылар елемей кетуі үшін енгізіңіз және нұсқаны (version) немесе кем дегенде тип пен өзгеріс күнін өткізіңіз. Бұл ескі оқиғаның жаңа кодты бұзуы қаупін азайтады.

Нақты мысал: өтініш статусы және екі есе өңдеу

Оқиғалық интеграцияны енгізу жоспары
Жүйелер мен оқиғалардың картасын жасаймыз, нұсқалар мен үйлесімділік ережелерін келісеміз.
Іске асыру жоспары

Мысалға мемлекеттік органды ойлаңыз: бір жүйеде сатып алу өтініші тұрады, бухгалтерия басқа жүйеде жүргізіледі. Өтініш статусы өзгергенде интеграция кезек арқылы оқиға жібереді.

«Төленді» статусы шешуші сәтке айналады. Бухгалтерия тұтынушысы оқиғаны алып, бухгалтерлік жазбаны жасайды. Бірақ кезек сол оқиғаны тағы да жіберуі мүмкін (мысалы, растау таймаутынан кейін). Егер тұтынушы қорғалған болмаса, нәтиже — екі жазба, қосымша есептеу, қолмен түзетулер.

Дедупликация әдетте сиқырсыз шешіледі: әр оқиға бірегей event_id және домен кілті (мысалы, request_id + статус) тасиды. Бухгалтерия жазба жасамас бұрын осы event_id өңделген бе немесе осы өтініш бойынша төлем жасалған ба екенін тексереді.

Осылай жұмыс істеуі үшін алдын ала келісу қажет: кім event_id ұсынады және оның бірегейлігін кім кепілдейді, «бірегей төлемнің» кілті қандай (өтініш, шот, төлем), өңделген оқиғалар журналы қайда сақталады және қанша уақыт, оқиға деректер жетпей келгенде не істеу, инциденттерді бөліп қарау жауапкершілігі кімде.

Егер оқиға қажетті деректерге қарағанда бұрын келсе, «өз ойыңмен толықтыру» қауіпті. Негізгі тәсіл — өңдеуді кейінге қалдыру немесе жетіспей тұрған деректерді бөлек сұрап, шарттар орындалғанда ғана бухгалтерлік жазбаны жасау. Қайталанулар идемпотенттікпен қорғалған жағдайда ғана қауіпсіз болады.

Ретрайлер, қателер және бақылау оңай әрі тиімді болуы тиіс

Ретрайлер уақытша ақаулардан өтуге көмектеседі: қысқа желі үзілуі, дерекқордың жүктелуі, сыртқы қызметтің қолжетімсіздігі. Бірақ егер қате тұрақты болса, ретрайлер зиян келтіреді. Мысалы, қате деректер келгенде сервис оны қайта-қайта өңдеуге тырысып, кезекті «өлген» хабарламаларға толтырады.

Ереже қарапайым: ретрайлер уақытша проблемаларға, тұрақты қателерге — жедел шығу және бөлек талдау аймағы.

Қате кезегі және кейінге қалдырылған өңдеу

Әдетте екі механизм қолданылады: кейінге қалдырылған қайта өңдеу (хабарлама белгілі бір үзіліспен қайта өңге салынады, мысалы 1 минут, одан кейін 5, одан кейін 30) және қате кезегі (dead-letter), мұнда N сәтсіз әрекеттен кейін хабарлама жіберіледі, негізгі ағын бұғатталмасын.

Бұл маңызды: бір жасырылған хабарлама бүкіл лентаны ұстап тұруға тиіс емес, мысалы өтініш статусын синхрондау кезінде.

Не логтау керек және қандай метрикаларға қарау

Логтар мақсаты — жеткілікті және нысаналы: event_id, домендік кілт (order_id, ticket_id, user_id), әрекет нөмірі және қате себебі, өңдеу нәтижесі (сәттілік, дубль ретінде өткізу, қате ретінде dead-letter).

Метрикалардан жиі жеткілікті: тұтынушының кешігуі (lag), ретрайлер үлесі, қателер пайызы және dead-letter көлемі. Бұл қайталанулар мен ретрайлердің өсуін жылдам байқауға көмектеседі.

Проблеманың қай жерде екенін анықтау үшін қарапайым тексеріс: бірдей event_id барлық тұтынушыларда бірдей қате берсе, деректер көзі бұзылған болуы ықтимал. Егер қате бір сервисте ғана немесе жүктемеге байланысты болса, тұтынушы (код, ресурстар, сыртқы тәуелділіктер) кінәлі болуы мүмкін.

Оқиғалық интеграцияда типтік қателер мен тұзақтар

Ең ауыр проблемалар әдетте "қай кезек таңдауға" емес, күтулерге байланысты. Адамдар синхронды API-дан әдеттерін ала келеді де, оқиғалар басқа тәртіпте әрекет етеді деп таңқалады.

Жиі тұзақ — оқиғалардың тәртібіне сену. Практикада хабарламалар кешігіп, ретрайлерден кейін бір-бірін басып озуы немесе әртүрлі партициялардан келуі мүмкін. Егер логика қатты тәртіпке тәуелді болса, ақыр соңында күй бұзылады.

Екінші қате — кезек дубльдерден құтқарады деп сену. Тіпті жақсы бапталған кезде де қайталанулар мүмкін: таймауттар, қайта жіберулер, тұтынушы құлауы және желі ақаулары. Дұрыс тәсіл — қайта жеткізуді қалыпты жағдай ретінде қарастырып, өңдеуді деректерді бұзбайтындай жобалау.

Көп жүйені жазатын қателік — жанама әсерлерді бақыламай жасау. Алдымен ақша алып, жазбаны жасап немесе хат жіберіп, содан кейін "өңделді" деген жазба түспей қалса, қайталап келсе екі есе әрекет болады.

Тағы бір тұзақ — нұсқа бақылауын қоспау. Өрістер өзгеріп, қосылып, қайта аталғанда ескі тұтынушы қате береді немесе деректерді бұрыс түсінеді. Нұсқа үйлесімділік ережелерін келісіңіз және оқиға нұсқасын анық көрсетіңіз.

Соңында, көпшілік қалдыратын нәрсе — инциденттен кейін қалпына келтіру жоспарының жоқтығы. Міндетті минимум: оқиғаларды уақытша қайта ойнауға мүмкіндік (replay) және эффектілерді екі еселеусіз қайта іске қосу жолы, өңделген хабарламалар журналы немесе идемпотенттік кілттер, деректерді қолмен салыстыру және түзету процедурасы, дубльдердің өсуі мен ретрайлерге арналған метрикалар мен ескертулер, қайта ойнауды шешетін жауапты тұлға мен процедура.

Продқа жіберер алдында қысқа чек-лист

Кілт бойымен жүйелік интеграция
Статустар, төлемдер, хабарламалар және аудит секілді бизнес-сценарийлерге сай интеграцияны толық дайындаймыз.
Жоба тапсыру

Релизке дейін оқиғалық интеграция бойынша негізгі пункттерді тексерген жөн. Олар жүйені «мінсіз» қылмаса да, түнгі инциденттер тәуекелін айтарлықтай азайтады, кезек өскенде және жүйелер арасында деректер «шайқалғанда».

  • Әр хабарламада бірегей оқиға идентификаторы және түсінікті домен кілті бар (order_id, user_id сияқты).
  • Өңдеуші қайталануларды қауіпсіз өткізеді: бір ғана өңдеу мен көп рет өңдеудің нәтижесі бірдей.
  • "Оқиға өңделді" белгісі сенімді жерде сақталады (өңделген event_id кестесі, мақсаттық жазбада бірегей индексті сақтау немесе ұқсас механизм).
  • Ретрайлер ойлана жасалған: қанша әрекет, қандай үзіліспен және одан кейін не болады (бөлек қате кезегі немесе түсінікті қолмен процедура).
  • Логтар мен метрикалар арқылы тез анықтап алуға болады: "қай оқиға және неге сынды" және төтенше жағдайда деректерді қолмен түзету процедурасы бар.

Ақылға қонымды тексеріс: нақты сценарийді (мысалы, өтініш статусы өзгеруі) алып, үш тест жүргізіңіз — қайта жеткізу, оқиғаның бірнеше минут кешігуі және өңдеушінің ортасында құлауы. Егер осыдан кейін деректер сәйкес келсе, сіз релизге жайлы жақынсыз.

Келесі қадамдар: енгізу және қолдау қалай жүргізіледі

Оқиғалық интеграция шексіз түзетулерге айналмасын десеңіз, брокерден бастап емес, нақты картинаны анықтаудан бастаңыз: қандай шешімдер оқиғаларға тәуелді және қателіктің құны қанша. Пайдасы көп тәсіл — бизнес-сценарилерден (тапсырыс құрылды, шот төленді, өтініш жойылды) бастау, содан кейін топиктер, кезектер және оқиға форматын талқылау.

Келесі кезең — жұмыс жоспары: жүйелер мен оқиғалар картасын жинау (кім жариялайды, кім оқиды), кепілдіктерді бекіту (не қабылданар, не қабылданбайды), қай жерде өңдеу күйі сақталатынын шешу, жүктеме мен ақауларға тесттер дайындау, қолдау ұйымдастыру (мониторинг, ескертулер, қолмен араласу ережелері және жаңартулар).

Тарихты сақтау туралы бөлек ойлану керек. "Неге статус өзгерді?" деген сұраққа жауап беру үшін бір ғана ағымдық мән жеткіліксіз. Трасс қажет: оқиғаның идентификаторы, уақыты, өңдеу нәтижесі, қате және әрекеттер саны.

Егер осындай интеграция инфрақұрылымын ірі ұйымдарда жасасаңыз (мемлекет, қаржы, денсаулық сақтау), мәселе көбіне сенімді серверлер, ашық қолдау және жауапкершілікті түсінікті бөлуге келеді. Қазақстанда бұл мәселені жүйелік интеграторлар мен өндірушілер, мысалы GSE.kz (gse.kz), интеграциялық қызметтермен қатар өздерінің S200 Series серверлері мен тәулік бойы техникалық қолдау желісі арқылы жабады.

FAQ

Неге бір оқиға екі не үш рет келуі мүмкін?

Көптеген брокерлер мен кезектер «кем дегенде бір рет» жеткізу кепілдігін береді. Егер тұтынушы хабарламаны өңдеп, бірақ `ack` жіберуге үлгермесе (немесе `ack` желідегі ақаудан жоғалса), брокер жеткізу расталмаған деп есептеп, хабарламаны қайта жібереді. Бұл - сенімділікті қамтамасыз ету механизмі, міндетті түрде интеграцияның қатесі емес.

Қашан сұраулар (API), ал қашан оқиғалар пайдаланған дұрыс?

Сұрау сізге «қазір жауап керек» болғанда және онысыз жалғастыра алмағанда ыңғайлы: мысалы, төлем қызметі төлем жасалмас бұрын тапсырыс бар-жоғын сұрайды. Оқиға — жүйе фактіні мәлімдейді және оны бірнеше тұтынушы білуі тиіс, бірақ дереу жауап күтілмейді. Практикалық ереже: егер сіз «сұрайсыз» — API сұрау, егер «хабарлайсыз» — оқиға жариялаңыз.

Оқиғада қай қандай өрістер болу керек, дубльдерді жеңілірек өткізу үшін?

Ең аз қажеті — жүйе-өзі берген бірегей `event_id` (көз жүйе анықтаған) және домендік кілт, мысалы `order_id`, `request_id` немесе `payment_id`. `event_id` бір хабарламаның қайта жеткізілуін сүзуге көмектеседі, ал кілт логикалық дубльдерден қорғауға пайдалы. Егер `event_id` тұтынушы тарапынан жасалса, ол сырттан келген қайта жеткізуден қорғамайды.

Оқиғаның өңделгенін сақтау қайда жақсырақ?

Көбінесе тұтынушының дерекқорындағы «өңделген оқиғалар» кестесі немесе коллекциясы қолданылады. Оған `event_id`, домендік кілт, уақыт және өңдеу нәтижесі жазылады, сонда қайта келгенде тез анықтап, әрекетті өткізіп жіберуге болады. Өңдеу фактісінің жазылуы сенімді болуы маңызды, әйтпесе қайталау бизнес-әрекетті қайталай алады.

Оқиғаны өңдеу мен "өңделді" жазбасын бір транзакцияда жазу керек пе?

Көп жағдайда — иә. Бір транзакцияда: `event_id` бұрын кездеспегенін тексеру, бизнес-өзгерісті енгізу, және «өңделді» деген жазба жасау. Осылайша ортасында құласаңыз, әрекет жасалып қойып, «өңделген» белгісі жоқ қалған жағдайдан сақтайсыз. Егер транзакция мүмкін болмаса, ең болмағанда қайтарылмайтын қадамдарды (ақша алу, жөнелту, хат жіберу) идемпотентті кілтпен қорғаңыз.

Тұтыншыдан сыртқы API-ге шақыру кезінде төлем/өтініштің екі есе жасалуын қалай болдырмауға болады?

Сыртқы API-ге шақыруда идемпотентті кілт жіберіңіз, сол арқылы қайта шақыру екінші объект жасамай, бұрынғы нәтижені қайтарады. Практикада кілт ретінде жиі `event_id` немесе «оқиға типі + объект id» комбинациясы пайдаланылады. Сол кезде қайталанған оқиға қайта сұраныс жібереді, бірақ сыртқы жүйе дубль жасамайды.

Кезекте оқиғалардың тәртібіне сенуге бола ма?

Оқиғалардың әрқашан тәртіппен келетінін күтпеу керек. Жүктеме астында және параллель өңдеуде хабарламалар кешігіп немесе бір-бірін басып озуы, ретрайлерден кейін тәртіп бұзылуы мүмкін. Сенімді тәсіл — объектіні мақсатты күйге келтіру және күй/уақыт/нұсқамен тексеру, емес бірқатар қадамдарды қатесіз орындауға сену.

Ретрайлерді қалай орнату керек, шексіз қате цикл құтылмас үшін?

Ретрайлер уақытша ақаулар үшін пайдалы: қысқа желі үзілуі, дерекқордың уақытша жүктелуі және т.б. Егер қате тұрақты болса (бұзылған деректер, үйлесімсіз схема), шексіз қайталай беру кезекті «өлі» хабарламаларға толтырады. Сондықтан әрекеттің санын шектеп, N сәтсіз әрекеттен кейін хабарламаны dead-letter-ке жіберген дұрыс.

Егер оқиға қажетті деректер пайда болғанға дейін келсе не істеу керек?

Не екенін ойлап «қосымша әкелмеу» қауіпсіз: әдетте хабарлама қажетті деректер базаға түсе қоймай келгенде оны кейінге қалдырады немесе қосымша сұрау жасап, деректер бар болғанда ғана керекті әрекетті орындайды. Ең бастысы — қайталанған кезде де идемпотенттік сақталсын.

Интеграциядағы проблемаларды тез табу үшін не логтау және қандай метрикаларды қадағалау керек?

Логтардан тез нәтижені табу үшін: `event_id`, домендік кілт (`order_id`, `ticket_id`, `user_id`), әрекет нөмірі және қате себебі, өңдеу нәтижесі (сәтті, дубльді өткізіп жіберді, қате ретінде dead-letter-ке жіберілді). Метрикалардан: тұтынушының артта қалуы (lag), ретрайлер үлесі, қателер пайызы және dead-letter көлемі жеткілікті. Бұл жүйелік проблемалардың қайда екенін жылдам ажыратуға көмектеседі.