Bağlantının tek sahibi kim? DynamoDB ile dağıtık kira (lease) deseni
Building resilient real-time streaming workers with Amazon DynamoDB leases · Siddhesh Tiwari
500 eşzamanlı toplantıyı işleyen bir gerçek zamanlı transkripsiyon servisi düşün. Her toplantı için bir işçi, kaynağa giden ayrı bir WebSocket bağlantısı tutuyor. Bir işçi çökerse 100'den fazla bağlantı düşüyor ve operatör servisi elle yeniden başlatana kadar bağlantı başına 2-3 dakika veri kaybı oluyor.
Problemin özü: her bağlantıya tam olarak bir işçi sahip olmalı, ama işçiler birbirinden bağımsız çöküyor, yeniden dağıtılıyor ve ölçekleniyor. Zorluklar dört tane: işçi çökmesi, kayan dağıtımlar (yeni görev başlarken eskisi bağlantılarını bırakır), yatay ölçekleme (eklemek kolay, çıkarırken bağlantıları devretmek zor) ve en tehlikelisi çift sahiplenme: iki işçi aynı bağlantıyı sahiplenip aynı kaynağa bağlanırsa çift veri işleme ve protokol hataları çıkar.
Çözümün anahtar fikri tek cümlede: DynamoDB koşullu yazmaları (conditional write), ayrı bir koordinasyon servisine gerek bırakmadan dağıtık kilit işlevi görür. Her bağlantının bir kirası var: süresi sınırlı bir sahiplik iddiası. İşçiler kirayı sürekli yenilemek (heartbeat) zorunda; bir işçi aniden durursa kira dolar ve başka bir işçi devralır. Tablo tek öğede hem kira bilgisini (lease_owner, lease_expires_at_ms) hem bağlantı durumunu (desired_state, ws_url, last_seq) tutuyor. Sahipsiz bağlantıları bulmak için desired_state ve lease_expires_at_ms üzerinde bir GSI var. SQS yalnızca hızlı bildirim kanalı: sahipliğin sürekli bir durum olduğunu, SQS’in ise tek seferlik görev teslimi için tasarlandığını açıkça belirtiyorlar.
Dikkat çekici bir dürüst not: kira süresi dolma kontrolü, işçilerin yerel saatlerine dayanıyor; yani saatler makul ölçüde senkron olmalı. Varsayılan kira süresi 20 saniye, heartbeat aralığı 5 saniye; saat kayması bu güvenlik payının çok içinde kalıyor.
Öne çıkanlar
- Sahiplik bir görev değil sürekli bir durumdur; bu yüzden kuyruk değil süresi dolan bir kayıtla modellenir.
- Koşullu yazma = atomik ‘şu koşulda yaz’ işlemi; ayrı kilit servisi olmadan dağıtık kilit sağlar.
- Kira süresi ile heartbeat aralığı birlikte seçilir: süre, aralığın birkaç katı olmalı ki gecikmeler yanlış devralmaya yol açmasın.
- Kira, saat doğruluğuna bağlı; senkronizasyonu varsaymak yerine kira süresini olası kaymayla payla.
- Zarif kapatma (graceful shutdown) ile dağıtım sırasında bağlantılar kayıpsız devredilebilir.
Neden önemli?
‘Tam olarak bir sahip’ gereksinimi çıktığı her yerde (zamanlanmış iş, lider seçimi, bağlantı yönetimi) kira deseni yeniden karşına çıkar. Önemli olan sahipliğin süresiz değil sürekli yenilenen bir iddia olması: çöken sahibin kilidi sonsuza kadar tutmasını engelleyen tek şey bu.
Sende karşılığı
Bunu PostgreSQL ile de kurabilirsin: UPDATE jobs SET owner = :me, expires_at = now() + interval '20 seconds' WHERE id = :id AND (owner IS NULL OR expires_at < now()) ve etkilenen satır sayısı 1 ise kira senin. Mobit’te zamanlanmış bir iş birden fazla örnekte çalışıyorsa (belge indeksleme, bildirim gönderme) aynı işi iki örneğin birden yapmadığından emin misin? ShedLock gibi Spring kütüphaneleri bu deseni hazır sunar. Tradebot’ta da bir borsa bağlantısını yalnızca bir sürecin tutması gerekiyorsa aynı kira mantığı çift işlem emri riskini önler.
Sözlük
- lease kira (süreli sahiplik)
- Belirli bir süre için geçerli olan ve yenilenmezse kendiliğinden biten sahiplik iddiası.
- conditional write koşullu yazma
- Yalnızca belirtilen koşul doğruysa gerçekleşen atomik yazma işlemi.
- heartbeat yaşam sinyali
- Bir bileşenin hâlâ ayakta olduğunu belirtmek için düzenli aralıklarla gönderdiği sinyal.
- graceful shutdown zarif kapatma
- Bir süreç kapanmadan önce işini ve bağlantılarını düzgünce devrederek bırakması.