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

> Skorları String'de tutup uygulamada sıralamak yerine Sorted Set kullanın: `ZADD` O(log N) günceller, `ZREVRANGE 0 99` ilk 100'ü zaten sıralı döner.

- Soruldu: 2026-06-07
- Yanıtlandı: 2026-06-10
- Soran: Sarp
- Etiketler: veritabani, redis, performans
- Kaynak: https://www.muhammetsafak.com.tr/sor-bakalim/redis-veri-tipleri-leaderboard-icin-sorted-set/
- Dil: tr-TR
- Yazar: Muhammet Şafak

---
**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?


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)**.

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.

1. **`ZADD` ile O(log N) güncelleme.** `ZADD leaderboard <score> <user>` bir üyenin skorunu O(log N)'de günceller. Oyuncu skoru değiştiğinde tek komut; tüm tabloyu dokunmanıza gerek yok. Skor değiştiği an set kendi içinde sıralı kalır.
2. **`ZREVRANGE` ile zaten sıralı ilk 100.** `ZREVRANGE leaderboard 0 99 WITHSCORES` en yüksek 100 oyuncuyu **zaten sıralı** olarak O(log N + 100)'de döner. Uygulama tarafında hiç sıralama yapmazsınız; milyonlarca oyuncu olsa da bu okuma neredeyse sabit maliyetli.
3. **`ZREVRANK` ile tek oyuncunun sırası.** "Ben kaçıncıyım?" sorusu `ZREVRANK leaderboard <user>` ile O(log N)'de cevaplanır. String yaklaşımında bunun için herkesi çekip saymak gerekirdi; ZSET'te tek komut.
4. **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.
5. **Büyük setlerde pencerele.** 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.

## İlgili Yazılar

- [Sadece 'pending' satırları taranan bir kuyruk tablosunda partial index kullanmalı mıyım?](https://www.muhammetsafak.com.tr/sor-bakalim/sadece-pending-satirlari-taranan-bir-kuyruk-tablosunda-partial-index-kullanmali-miyim/) — Sor Bakalım
- [Bakiye güncellemede race condition: Pessimistic Lock mı, Redlock mı?](https://www.muhammetsafak.com.tr/sor-bakalim/bakiye-guncellemede-race-condition-pessimistic-lock-mu-redlock-mu/) — Sor Bakalım
- [Elasticsearch'te 'search-as-you-type' performansını edge n-gram ile nasıl optimize ederim?](https://www.muhammetsafak.com.tr/sor-bakalim/elasticsearch-anlik-arama-edge-ngram-ile-optimizasyon/) — Sor Bakalım
