İçeriğe geç

Bir faturanın güvenilirliği

Klavye: ← → ile gezinin, F tam ekran, O genel bakış.

Tan, ciddi bir ifadeyle

Muhammet Şafak — Sunumlar

Bir faturanın güvenilirliği

Numara, yazma, tekrar ve sonuç: bir fatura yolda dört kez ters gidebilir.

Muhammet Şafak

Bölüm 01

Numara

E-faturada numara hem mükerrersiz hem boşluksuz olmak zorunda.

Numarayı geç üretirsem race, erken üretirsem gap.

Muhammet ŞafakE-fatura entegrasyonunda numara çakışması

İki kısıt

Dört yaklaşım, iki kısıt

Veritabanının kendi sequence'ı (SEQUENCE, AUTO_INCREMENT) rollback'te tüketilen değeri geri vermez; boşluk üretir.
YaklaşımMükerrersizBoşluksuzKırılma
Gönderimde MAX()+1HayırEvetParalel worker'da çakışma
Enqueue'da üretEvetHayırBaşarısız ya da iptal → gap
DB sequenceEvetHayırRollback değeri geri vermez → gap
JIT rezervasyonEvetEvetBedeli: erken commit şart

JIT rezervasyon

Numara, gönderimden hemen önce

  1. Adım 1: KilitlelockForUpdate
  2. Adım 2: Rezerve etreserved_no boşsa sayaç++
  3. Adım 3: Erken commitstatus = SENDING
  4. Adım 4: Entegratörkilidin dışında
  5. Adım 5: Retryaynı reserved_no

Kilit DB state'i için tutulur, dış I/O için değil.

Muhammet ŞafakEntegratör çağrısı 200 ms ile 2 saniye sürer · sade.dev

Bölüm 02

Teslim

Fatura veritabanına, event RabbitMQ'ya: iki sistem, tek atomik adım yok.

Dual-write

İki sisteme yazmak

Dual-writesave() ve publish() ayrı
  • Yayın düşer → kayıp event
  • Rollback olur → hayalet event
  • DB::transaction RabbitMQ'yu kapsamaz
Transactional outboxYazma tek sisteme iner
  • Fatura ve outbox satırı aynı commit'te
  • Ayrı bir süreç broker'a yayımlar
  • Dual-write tek write'a iner

Tekrar

Tekrar teslim zararsız olmalı

Yalnız at-least-onceIdempotent tüketici
TeslimEn az bir, bazen iki kezEn az bir, bazen iki kez
Kayıtİşlenen id tutulmazprocessed_messages, unique kısıt
Transactionİş ve damga ayrıİş ve damga aynı transaction'da
SonuçTekrar, etkiyi tekrarlarEffectively-once

Veriyi tek bir sisteme yaz, tekrarı tüketicide bastır, hassas alanı yola çıkmadan mühürle.

Muhammet ŞafakOutbox, idempotent tüketim ve alan şifrelemesi

Bölüm 03

Sonuç

Outbox teslimi garanti etti; aynı sonucu garanti etmedi.

Gerçek denklem

sonuç = f(mesaj, gizli girdiler)

Üretim ile tüketim arası milisaniye de olabilir, yirmi dakika da, üç gün de.

Gizli girdiler

Altı gizli girdi

Event-driven bir fatura akışında karşılaşılan altı gizli girdi.
GirdiSomut hâli
ZamanBelge tarihi için o anki saati okumak
VeritabanıOluşturulurken önek X, gönderilirken Y
KonfigürasyonAynı izin listesi iki ayrı serviste
Dış sistem"Bu zaten var", ama neyin var olduğu belirsiz
OrtamBir framework uyarıyı yutar, diğeri exception'a çevirir
WorkerParalel replica, kilit, tekrar teslim

Gürültülü başarısızlık, sessiz yanlış sonuca yeğdir

Dört hamle

  1. Adım 1: Bağlamı dondurüretim anında
  2. Adım 2: Zaman girdidirretry zamanı değiştirmez
  3. Adım 3: Çatalı isimlendirgerekçeyi log'a yaz
  4. Adım 4: Sessizce çözmebelirsizlikte dur
Tan, el sallarken

Teşekkürler

muhammetsafak.com.tr

Karara giren dondurulur, girmeyen referansla taşınır.

Paylaş, göm, indir