Bir faturanın güvenilirliği
Klavye: ← → ile gezinin, F tam ekran, O genel bakış.

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.
İki kısıt
Dört yaklaşım, iki kısıt
| Yaklaşım | Mükerrersiz | Boşluksuz | Kırılma |
|---|---|---|---|
| Gönderimde MAX()+1 | Hayır | Evet | Paralel worker'da çakışma |
| Enqueue'da üret | Evet | Hayır | Başarısız ya da iptal → gap |
| DB sequence | Evet | Hayır | Rollback değeri geri vermez → gap |
| JIT rezervasyon | Evet | Evet | Bedeli: erken commit şart |
JIT rezervasyon
Numara, gönderimden hemen önce
- 1Adım 1: Kilitle
lockForUpdate - 2Adım 2: Rezerve et
reserved_no boşsa sayaç++ - 3Adım 3: Erken commit
status = SENDING - 4Adım 4: Entegratör
kilidin dışında - 5Adım 5: Retry
aynı reserved_no
Kilit DB state'i için tutulur, dış I/O için değil.
Bölüm 02
Teslim
Fatura veritabanına, event RabbitMQ'ya: iki sistem, tek atomik adım yok.
Dual-write
İki sisteme yazmak
- Yayın düşer → kayıp event
- Rollback olur → hayalet event
- DB::transaction RabbitMQ'yu kapsamaz
- 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-once | Idempotent tüketici | |
|---|---|---|
| Teslim | En az bir, bazen iki kez | En az bir, bazen iki kez |
| Kayıt | İşlenen id tutulmaz | processed_messages, unique kısıt |
| Transaction | İş ve damga ayrı | İş ve damga aynı transaction'da |
| Sonuç | Tekrar, etkiyi tekrarlar | Effectively-once |
Veriyi tek bir sisteme yaz, tekrarı tüketicide bastır, hassas alanı yola çıkmadan mühürle.
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
| Girdi | Somut hâli |
|---|---|
| Zaman | Belge tarihi için o anki saati okumak |
| Veritabanı | Oluşturulurken önek X, gönderilirken Y |
| Konfigürasyon | Aynı izin listesi iki ayrı serviste |
| Dış sistem | "Bu zaten var", ama neyin var olduğu belirsiz |
| Ortam | Bir framework uyarıyı yutar, diğeri exception'a çevirir |
| Worker | Paralel replica, kilit, tekrar teslim |
Gürültülü başarısızlık, sessiz yanlış sonuca yeğdir
Dört hamle
- 1Adım 1: Bağlamı dondur
üretim anında - 2Adım 2: Zaman girdidir
retry zamanı değiştirmez - 3Adım 3: Çatalı isimlendir
gerekçeyi log'a yaz - 4Adım 4: Sessizce çözme
belirsizlikte dur

Teşekkürler
Karara giren dondurulur, girmeyen referansla taşınır.