Mesaj kuyruklarında at-most-once, at-least-once ve exactly-once teslim garantileri ne anlama gelir? Idempotent consumer nasıl yazılır?
Cevap
| Garanti | Anlamı | Nasıl oluşur | Risk |
|---|---|---|---|
| At-most-once | Mesaj en fazla bir kez işlenir | Consumer önce ack/commit eder, sonra işler | Çökme durumunda mesaj kaybolur |
| At-least-once | Mesaj en az bir kez işlenir | Önce işler, sonra ack/commit eder | Çökme veya timeout'ta mesaj tekrar gelir |
| Exactly-once | Etki tam olarak bir kez oluşur | Ek mekanizmalar gerekir | Pahalı, kapsamı sınırlı |
Çoğu gerçek sistem at-least-once kullanır (RabbitMQ manuel ack, Kafka'da işlem sonrası offset commit, SQS) ve tekrarları consumer tarafında zararsız hale getirir.
Exactly-once neden zor?
Ağda bir onay mesajı kaybolduğunda gönderen, mesajın işlenip işlenmediğini bilemez; ya tekrar gönderir (duplicate) ya göndermez (kayıp). Kafka'nın exactly-once semantics özelliği (idempotent producer + transactions) yalnızca Kafka'dan okuyup Kafka'ya yazan akışlar için geçerlidir; consumer bir DB'ye yazıyor veya e-posta gönderiyorsa bu garanti dışarıya uzanmaz. Pratikte hedef: at-least-once teslim + idempotent işleme = etkin exactly-once.
Idempotent consumer
Her mesajın benzersiz bir ID'si olur; işlenen ID'ler iş verisiyle aynı transaction'da kaydedilir.
CREATE TABLE processed_messages (
message_id text PRIMARY KEY,
processed_at timestamptz DEFAULT now()
);def handle(msg):
with db.transaction():
inserted = db.execute(
"INSERT INTO processed_messages (message_id) VALUES (%s) "
"ON CONFLICT DO NOTHING", (msg.id,)).rowcount
if inserted == 0:
return # daha önce işlenmiş, atla
db.execute("UPDATE accounts SET balance = balance + %s WHERE id = %s",
(msg.amount, msg.account_id))
msg.ack() # commit'ten sonra ackDiğer teknikler: doğal olarak idempotent işlemler (SET status = 'paid' gibi, balance + 10 değil), unique constraint'ler, versiyon numaraları.
İlgili kavramlar
- Dead letter queue (DLQ): belirli sayıda denemeden sonra hâlâ başarısız olan mesajlar ayrı kuyruğa alınır ki kuyruğu tıkamasın (poison message).
- Sıralama: Kafka sıralamayı yalnızca partition içinde garanti eder; aynı entity'nin mesajları aynı key ile gönderilmelidir.
İlgili Sistem Tasarımı soruları
- Mesaj kuyruğu (RabbitMQ, Kafka) ne zaman kullanılır?
- Monolith ile mikroservis mimarisi arasındaki fark nedir? Mikroservislere ne zaman geçilmeli?
- CAP teoremi nedir? Gerçek sistemlerde nasıl yorumlanır?
- Dikey ve yatay ölçekleme arasındaki fark nedir?
- Hangi cache stratejilerini biliyorsunuz?
- REST ile GraphQL arasındaki farklar nelerdir?
Bu konuda başka bir soru biliyor musun?
Mülakatta karşılaştığın soruları ekle, onaylandıktan sonra yayına alınsın.