Protobuf ile Kompakt Video Meta Verileri
Veri alım işçimiz (ingest worker) her iki saatte bir binlerce trend videoyu çekiyor. Bu verileri üç servise gönderiyoruz: bir sıralama servisi, bir önbellek ısıtıcı (cache warmer) ve bir analitik işi.
Uzun bir süre boyunca bu verileri taşımak için JSON kullandık. Sorun çıkana kadar işe yarıyordu.
JSON formatında tek bir video kaydı 2,4 KB yer kaplıyordu. 40.000 kaydı üç farklı servise taşımak, her iki saatte bir 280 MB tekrarlanan metin taşımak anlamına geliyordu. Bu durum bant genişliğini israf ediyor ve PHP işçilerimizi yavaşlatıyordu.
Protocol Buffers (Protobuf) sistemine geçtik. İşte neden böyle yaptığımız ve bunun sistemimizi nasıl değiştirdiği.
JSON ile İlgili Üç Temel Sorun:
- Boyut: JSON, her kayıtta alan adlarını tekrarlar. "viral_score_24h" gibi bir alan adı, sadece 8 baytlık bir sayıyı taşımak için 15 bayt kullanır.
- Ayrıştırma Maliyeti (Parse Cost): Bir servisin sadece iki alana ihtiyacı olsa bile PHP'nin tüm JSON bloğunu ayrıştırması gerekir.
- Şema Kayması (Schema Drift): JSON'un bir sözleşmesi (contract) yoktur. Eğer bir servis bir alanı değiştirirse, diğerleri çalışma zamanında (runtime) sessizce bozulur.
Protobuf Bunu Nasıl Çözdü:
Protobuf, isimler yerine alan numaralarını kullanır. Tek bir doğruluk kaynağı (single source of truth) olarak bir .proto dosyası kullanır. Bu dosya PHP, Python ve Go için kod üretir. Şemayı değiştirirseniz, kod derleme aşamasında hata verir. Bu, çalışma zamanı hatalarını derleme zamanı hatalarına dönüştürür.
Sonuçlar:
Bu değişiklikleri bir hafta boyunca ölçtük:
- Veri yükü boyutu (Payload size): 2,4 KB'dan 720 bayta düştü (%70 azalma).
- PHP Kodlama (Encode) süresi: 310 ms'den 95 ms'ye düştü.
- Go Çözme (Decode) süresi: 140 ms'den 38 ms'ye düştü.
- Bant genişliği: Döngü başına 280 MB'dan 84 MB'a düştü.
Protobuf Ne Zaman Kullanılmalı:
Her şey için kullanmayın. Eğer veri yükleriniz küçükse veya insanların bunları kolayca okumasına ihtiyacınız varsa JSON ile devam edin. Protobuf'u, hızın ve katı sözleşmelerin en önemli olduğu yüksek hacimli dahili trafik için kullanın.
Genel API'lerimiz hâlâ JSON kullanıyor. Dahili servislerimiz ise Protobuf kullanıyor.