<

Şebekesiz Geçen 6 Saat: Kenar Tamponlamanın İnce Ayarı

Eylül'ün son haftası, bölgesel bir fiber kesintisi iki GSM operatörünün backhaul'unu birden götürdü ve Aydın-Denizli hattındaki 1.800 cihazımız saat 11.04'te aynı anda karanlığa gömüldü. Kesinti tam 6 saat 12 dakika sürdü. Müşterilerimiz soğuk zincir takibi yapan gıda firmalarıydı; o 6 saatin verisi "olsa iyi olur" değil, denetimde ibraz edilmesi zorunlu kayıttı. Saat 17.16'da şebeke geri geldiğinde asıl sınav başladı: 1.800 cihaz, her birinde ortalama 4 bin 400 bekleyen ölçüm, hepsi aynı anda anlatmaya başladı. O akşam öğrendik ki kenar tamponlama iki ayrı sınavdır — biriktirmek ve geri boşaltmak — ve biz sadece ilkine çalışmıştık.

Veri Oradaydı, Sıralama Felaketti

Biriktirme tarafı aslında iyi çalıştı. Cihazlarımızda store-and-forward katmanı vardı: bağlantı yokken ölçümler yerel flash'a yazılıyor, bağlantı gelince gönderiliyordu. 6 saatlik kesintiyi kapasite olarak rahat karşıladık çünkü tampon boyutunu en kötü senaryo olarak 72 saate göre tasarlamıştık. Sorun, boşaltma stratejisindeydi. Firmware, kuyruğu LIFO mantığıyla değil FIFO ile gönderiyordu — kağıt üzerinde doğru karar, kronoloji korunuyor. Ama şu detay gözden kaçmıştı: cihaz tamponu boşaltırken canlı ölçümleri kuyruğun arkasına ekliyordu. 4 bin 400 mesajlık kuyruğu 2G hızında boşaltmak 40 dakikadan fazla sürüyordu ve bu süre boyunca operasyon ekibi cihazların şu anki durumunu göremiyordu. Soğuk zincirde 40 dakika körlük, az önce 6 saat körlük yaşamış bir müşteriye anlatılabilir bir şey değil.

İlk düzeltme kavramsal olarak küçük, etkisi büyüktü: kuyruğu ikiye ayırdık. Canlı veri her zaman öncelikli kanaldan anında gider; tarihsel tampon ise arka planda, ayrı bir topic üzerinden, bant genişliğinin artanıyla boşalır. Şebeke döner dönmez operasyon 30 saniye içinde güncel sıcaklıkları görür, geçmiş ise sessizce dolar. Bu ayrımın backend'de de karşılığı var: canlı kanal alarm motoruna, tarihsel kanal ise doğrudan zaman serisi veritabanına akar — geçmiş veri, dönerken bir daha alarm tetiklemez. Kesinti günü, 6 saat önceki "sıcaklık 9 dereceye çıktı" ölçümleri geri akarken alarm motoru 700 küsur bayat alarm üretmişti; nöbetçi mühendisin telefonu kelimenin tam anlamıyla kilitlenmişti.

Herkes Aynı Anda Konuşursa Kimse Duyulmaz

İkinci sınav backend tarafındaydı. 1.800 cihazın senkron dönüşü, normalde saniyede 120 mesaj işleyen ingestion hattımıza tepe anda saniyede 3 bin 800 mesaj bindirdi. MQTT broker bunu kaldırdı ama arkadaki yazma katmanı kaldırmadı: TimescaleDB'ye toplu insert yapan servis, bağlantı havuzunu tüketip 502 dönmeye başladı, mesajlar consumer'da birikti, lag 25 dakikaya vurdu. İşin ironisi, veriyi sahada 6 saat sapasağlam saklamış, sonra kendi veri merkezimizde düşürme riskiyle karşılaşmıştık.

Buradaki dersimiz, thundering herd'ün sadece reconnect sorunu olmadığıydı. Çözümü iki uçta birden kurduk. Cihaz tarafında: tampon boşaltma hızı artık sunucudan gelen bir "tempo" parametresine bağlı. Backend sıkışınca broker üzerinden yayınlanan tek bir retained mesajla bütün filoya "tarihsel boşaltmayı saniyede 1 mesaja düşür" diyebiliyoruz; normal zamanda bu limit 10. Ayrıca her cihaz, boşaltmaya başlamadan önce kendi ID'sinden türetilmiş 0-300 saniyelik bir gecikme bekliyor; dönüş dalgası artık dik bir duvar değil, yayvan bir tepe. Backend tarafında: tarihsel kanalın önüne Kafka benzeri bir tampon koyduk (o dönemde Redis Streams kullandık, bütçe sebebiyle); yazma servisi kendi hızında tüketiyor, tepe yükü kuyruk emiyor.

Flash'ın Sessiz Ölümü ve Zaman Damgası Yalanları

Tamponlamanın kimsenin panele koymadığı iki maliyeti daha var. Birincisi flash ömrü. İlk tasarımda her ölçümü geldiği anda ayrı ayrı flash'a yazıyorduk; dakikada bir ölçüm, günde 1.440 yazma, NOR flash'ta sektör silme döngüleriyle çarpınca bazı cihazlarda tampon bölgesi iki yılda ölüyordu. Ölen tampon sinsidir: cihaz çalışır, canlı veri akar, ama kesinti geldiğinde saklayamaz — yani hata tam da ihtiyaç anında ortaya çıkar. Çözüm: ölçümleri RAM'de 15 dakikalık bloklar halinde toplayıp flash'a tek seferde, CRC'li kayıtlar olarak yazmak ve bölgeye wear-leveling eklemek. Yazma sayısı 96'ya indi, projeksiyonda tampon ömrü cihaz ömrünü geçti. Bedeli: ani güç kaybında en fazla 15 dakikalık veri riski. Bunu da kritik alarm ölçümlerini blok beklemeden anında yazarak dengeledik — veri sınıflandırması yine karşımıza çıktı.

İkinci maliyet zaman. Kesintide biriken verinin değeri, zaman damgasının doğruluğu kadardır. Cihazlarımız NTP ile senkron oluyordu; peki 6 saat şebekesiz kalan, üstüne bir de güç kesintisiyle yeniden başlayan cihazın saati? RTC pili zayıflamış üç cihazda saat 1 Ocak 2000'e dönmüştü ve o cihazlar kesinti boyunca topladıkları veriyi 26 yıl öncesine damgalamıştı. Veritabanı bunları sessizce kabul etti; fark eden, denetim raporu çeken bir müşteri oldu. Şimdi her tampon kaydında iki alan var: cihazın duvar saati ve açılıştan beri sayan monoton sayaç. Cihaz şebekeye dönüp gerçek zamanı öğrendiğinde, backend monoton sayaç üzerinden geçmişe doğru doğru zamanları yeniden hesaplıyor. RTC'ye güvenmeyi bıraktık; RTC artık sadece bir ipucu.

Sıkıştırmayı da bu vesileyle masaya yatırdık. Tarihsel kanal zaten gecikmeye toleranslı olduğu için ölçümleri cihazda 15 dakikalık bloklar halinde delta kodlama ve hafif bir sıkıştırmayla paketleyip göndermeye başladık; ortalama payload, ölçüm başına 96 bayttan 14 bayta indi. Bunun üç getirisi oldu: 6 saatlik bir tamponun boşalma süresi 40 dakikadan 9 dakikaya düştü, aylık GSM veri faturası gözle görülür azaldı ve backend'e binen mesaj sayısı — blok başına tek mesaj — kırkta birine indi. Canlı kanala dokunmadık; orada tek ölçümün 2 saniyede ekranda olması, her türlü verimlilikten daha değerli.

Tampon Bir Özellik Değil, Sözleşmedir

O kesintiden sonra müşterilerimizle yaptığımız sözleşmelere ölçülebilir bir madde girdi: "72 saate kadar şebeke kesintisinde veri kaybı yok; şebeke dönüşünde canlı görünürlük 60 saniye içinde, tam tarihsel bütünlük 4 saat içinde sağlanır." Bu cümleyi yazabilmek, arkasındaki bütün mühendisliğin özetidir — kuyruk ayrımı, tempo kontrolü, wear-leveling, monoton saat. Ve her çeyrekte bir "kesinti tatbikatı" yapıyoruz: rastgele seçilen 50 cihazın SIM'ini uzaktan 8 saatliğine kapatıp dönüş davranışını ölçüyoruz. Son tatbikatta tarihsel bütünlük 2 saat 40 dakikada tamamlandı, sıfır bayat alarm üretildi.

Edge buffering, broşürlerde tek cümlelik bir özelliktir: "cihaz offline veri saklar." Sahada ise en az beş ayrı mühendislik kararının kesişimi: neyi sakla, nasıl yaz, ne zaman gönder, hangi hızda gönder, hangi saatle damgala. Bu kararların her birinin yanlış varsayılanı, kesinti gününe kadar görünmezdir. Kendi filonuzda "offline destekliyoruz ama dönüşler hep sancılı" durumu yaşıyorsanız buradan yazın; tatbikat senaryomuzu ve kuyruk ayrımı tasarımını olduğu gibi paylaşırım, çünkü bunları öğrenmenin pahalı yolunu biz zaten ödedik.

Fiber kesintisini yaşadığımız o eylül gününün panosunun ekran görüntüsü hâlâ wiki'mizin başında durur. Altında tek satır yazar: "Veri kaybetmedik. Ama altı saat boyunca bunu bilmiyorduk." Kenar tamponlamanın ince ayarı, tam olarak o cümleyi bir daha yazmamak içindir.

📅 Yayınlanma:  ·  Yakup Zengin