İçeriğe geç
Muhammet Şafak
en
Soran: Sarp Cevaplandı:

Redis'te canlı leaderboard için neden Sorted Set kullanmalıyım?


Soru

Bir oyun platformu için canlı leaderboard (en yüksek skorlu ilk 100 oyuncu) tasarlayacağım; milyonlarca oyuncunun skoru anlık değişiyor. Veriyi Redis'te tutmak istiyorum. Her oyuncunun skorunu düz bir String anahtarda (`user:123:score`) tutup her seferinde tüm kullanıcıları çekip sıralamak yerine Redis'in Sorted Set (ZSET) veri tipini kullanmanın mimari avantajları ve zaman karmaşıklığı (O(log N)) analizi nedir?

Cevap

Kısa cevap: Skorları user:123:score gibi düz String’lerde tutup uygulamada sıralama — bu okuma başına milyonlarca anahtar üzerinde O(N log N), üstelik her seferinde her şeyi yeniden çekersiniz. Doğru araç Sorted Set (ZSET).

Kısa cevap

Asıl mesele şu: leaderboard’ın doğası “sırala ve ilk N’i ver”. Bu işi okuma anında yapmaya çalışırsanız ölçek sizi ezer; sıralamayı yazma anına taşımanız gerekir. Redis’i bu şekilde sıcak yolun ortasına koyarken cache tarafındaki tuzaklara da bakmakta fayda var; stampede’i ayrı bir kayıtta ele almıştım.

Neden

  1. Skip-list, sıralamayı yazarken yapar. ZSET’in arkasındaki skip-list yapısı her şeyi siz yazdıkça sıralı tutar. Yani maliyet okuma anına değil yazma anına dağılır; okuma ucuz ve oyuncu sayısından neredeyse bağımsız kalır.
  2. Okuma maliyeti oyuncu sayısından bağımsızlaşır. ZREVRANGE leaderboard 0 99 WITHSCORES en yüksek 100 oyuncuyu zaten sıralı olarak O(log N + 100)‘de döner; milyonlarca oyuncu olsa da bu okuma neredeyse sabit maliyetlidir.
  3. String yaklaşımı her soru için her şeyi çeker. “Ben kaçıncıyım?” gibi tek bir soru için bile herkesi çekip saymak gerekir; ZSET’te aynı soru tek komuttur.

Ne yapmalı

  1. Skoru ZADD ile güncelleyin. ZADD leaderboard <score> <user> bir üyenin skorunu O(log N)‘de günceller. Oyuncu skoru değiştiğinde tek komut; tüm tabloya dokunmanıza gerek yok. Skor değiştiği an set kendi içinde sıralı kalır.
  2. İlk 100’ü ZREVRANGE ile okuyun. ZREVRANGE leaderboard 0 99 WITHSCORES yeterli; uygulama tarafında hiç sıralama yapmazsınız.
  3. Tek oyuncunun sırasını ZREVRANK ile alın. “Ben kaçıncıyım?” sorusu ZREVRANK leaderboard <user> ile O(log N)‘de cevaplanır.
  4. Büyük setlerde pencereleyin. Devasa setler için periyodik snapshot’lar ve zaman pencereli board’lar (günlük/haftalık ayrı anahtarlar) kullanın. Eşitliklere dikkat: aynı skorlular lexicographic sıralanır; gerekiyorsa skora bir tiebreaker (örn. zaman damgası) gömerek sırayı deterministik yapın.

Sonuç: ZSET tam da canlı leaderboard için tasarlanmış bir veri tipi; String + uygulama tarafı sıralama yerine onu kullanın. Sıralamayı okuma anından alıp yazma anına taşıdığınız an, milyonlarca oyuncuda bile leaderboard’ın anlık ve ucuz çalışır.

Paylaş:

Yorumlar

Yorum yapmak için GitHub hesabınızla giriş yapmanız yeterli. Yorumlar GitHub Discussions üzerinde saklanır.

Diğer Sorular

Tüm sorular

Sitede Ara

Yazı, proje ve sayfalarda arama yapmak için yazmaya başlayın.

Esc ile kapat Pagefind ile güçlendirildi