Redis Sorted Sets: praktische Anwendungsfaelle jenseits von Rankings
AI generated
SET
TTL
Redis · Sorted Sets · Queues · Zeitreihen
Redis Sorted Sets
praktische Anwendungsfaelle jenseits von Rankings

Sorted Sets gelten meist als Werkzeug fuer Leaderboards, sind aber eine der vielseitigsten Datenstrukturen in Redis. Mit einer nach Score sortierten Skip List im Hintergrund eignen sich Sorted Sets ebenso fuer Zeitreihen, verzoegerte Job-Ausfuehrung und Prioritaets-Warteschlangen, oft ohne zusaetzliche Infrastruktur neben Redis selbst.

18 Min. Lesezeit ZADD · ZRANGEBYSCORE · ZPOPMIN · Skip List Redis 6.x · 7.x

1. Sorted Sets sind mehr als Leaderboards

Ein Sorted Set kombiniert die Eigenschaften eines Sets, eindeutige Mitglieder, mit einer zweiten Dimension: jedem Mitglied ist ein Fliesskomma-Score zugeordnet, nach dem Redis die Menge automatisch sortiert haelt. Die meisten Einfuehrungen zu Redis erklaeren Sorted Sets ausschliesslich am Beispiel eines Spiele-Leaderboards, bei dem der Score den Punktestand eines Spielers repraesentiert. Das ist zutreffend, greift aber deutlich zu kurz, denn die zugrundeliegende Datenstruktur, eine Skip List kombiniert mit einer Hashtabelle, macht das Sorted Set zu einem der vielseitigsten Werkzeuge in Redis.

Der entscheidende Vorteil eines Sorted Sets gegenueber einer Liste liegt darin, dass Einfuegungen automatisch an der richtigen sortierten Position landen, ohne dass die Anwendung selbst sortieren muss. Der entscheidende Vorteil gegenueber einem einfachen Set liegt in der Ordnung: Waehrend ein Set keine Reihenfolge garantiert, liefert ein Sorted Set Bereichsabfragen nach Score in logarithmischer Zeit. Diese Kombination aus Eindeutigkeit, Ordnung und effizienten Bereichsabfragen macht Sorted Sets zur natuerlichen Struktur fuer alles, was sich als Wert mit einer sortierbaren Dimension modellieren laesst: Zeit, Prioritaet, Entfernung oder eben Punktestand.

Dieser Beitrag zeigt bewusst die Anwendungsfaelle jenseits klassischer Rankings: Zeitreihen-Speicherung, verzoegerte Job-Ausfuehrung und Prioritaets-Warteschlangen. Alle drei Muster nutzen denselben Kern-Mechanismus des Sorted Sets, nur mit unterschiedlicher Bedeutung des Score-Werts.

Wer bereits mit Hashes, Listen und Sets vertraut ist, wird beim Sorted Set schnell erkennen, dass es keine grundsaetzlich neue Denkweise erfordert, sondern lediglich eine zusaetzliche, konsequent genutzte Dimension: den Score. Genau diese Dimension macht das Sorted Set zum Schweizer Taschenmesser unter den Redis-Datentypen fuer alles, was Ordnung braucht.

2. Grundlagen: ZADD, ZSCORE, ZRANGE

ZADD fuegt ein Mitglied mit seinem Score in ein Sorted Set ein oder aktualisiert den Score, falls das Mitglied bereits existiert. Die Signatur ist ZADD key score member, wobei mehrere Score-Member-Paare in einem Aufruf uebergeben werden koennen. Zusaetzliche Flags wie NX, XX, GT und LT steuern das Verhalten bei bereits existierenden Mitgliedern: GT aktualisiert den Score nur, wenn der neue Wert groesser ist als der bisherige, praktisch fuer High-Score-Tracking, bei dem nur Verbesserungen gespeichert werden sollen.

ZSCORE liefert den aktuellen Score eines einzelnen Mitglieds, ZRANK und ZREVRANK die Position eines Mitglieds innerhalb der sortierten Reihenfolge, aufsteigend beziehungsweise absteigend. ZRANGE key start stop liefert einen Ausschnitt nach Rang, waehrend die Option WITHSCORES die zugehoerigen Score-Werte mitliefert. Seit Redis 6.2 vereint ZRANGE mit der Option BYSCORE oder BYLEX die Funktionalitaet der frueher separaten Commands ZRANGEBYSCORE und ZRANGEBYLEX in einem einzigen, flexibleren Befehl.


# Sorted Sets: basic score-based membership
redis-cli ZADD leaderboard:season1 1200 "player:42"
redis-cli ZADD leaderboard:season1 980 "player:17"
redis-cli ZADD leaderboard:season1 GT 1350 "player:42"
redis-cli ZSCORE leaderboard:season1 "player:42"
redis-cli ZRANK leaderboard:season1 "player:17"
redis-cli ZREVRANGE leaderboard:season1 0 2 WITHSCORES
redis-cli ZINCRBY leaderboard:season1 50 "player:17"
redis-cli ZCARD leaderboard:season1

3. Score-basierte Abfragen mit ZRANGEBYSCORE

Waehrend ZRANGE nach Rangposition abfragt, filtert ZRANGEBYSCORE nach dem Score-Wert selbst, mit inklusiven und exklusiven Grenzen. Der Ausdruck ZRANGEBYSCORE key min max liefert alle Mitglieder mit einem Score zwischen min und max, inklusive beider Grenzen. Ein vorangestelltes Klammer-Zeichen wie in (1000 macht die Grenze exklusiv. Die Spezialwerte -inf und +inf erlauben offene Bereiche, etwa alle Mitglieder ab einem bestimmten Score ohne obere Grenze.

Diese Score-basierte Filterung ist der zentrale Mechanismus, der Sorted Sets fuer Zeitreihen und Delayed Queues nutzbar macht, wie die naechsten Abschnitte zeigen. Ergaenzend erlaubt ZRANGEBYSCORE mit LIMIT offset count eine Paginierung innerhalb des gefilterten Bereichs, ohne dass der komplette Bereich zum Client uebertragen werden muss. Fuer alphanumerische Sortierung bei identischem Score, etwa fuer Autovervollstaendigung, gibt es die Lex-Range-Variante mit den Grenzen [a und [z als inklusive Zeichenketten-Grenzen.


# Score-based range queries: inclusive, exclusive, open-ended
redis-cli ZADD prices:sku42 100 "2026-07-01"
redis-cli ZADD prices:sku42 115 "2026-07-10"
redis-cli ZADD prices:sku42 99 "2026-07-20"
redis-cli ZRANGEBYSCORE prices:sku42 100 120
redis-cli ZRANGEBYSCORE prices:sku42 "(100" "+inf"
redis-cli ZRANGEBYSCORE prices:sku42 -inf 105 LIMIT 0 1
redis-cli ZCOUNT prices:sku42 100 120

4. Zeitreihen mit Sorted Sets modellieren

Ein haeufig unterschaetzter Anwendungsfall fuer Sorted Sets ist die Speicherung von Zeitreihen-Daten, bei denen der Score schlicht ein Unix-Timestamp ist. Jedes Ereignis wird als Mitglied mit seinem Zeitstempel als Score eingefuegt: ZADD sensor:temp:device42 1721742000 "22.4". Da Sorted Sets automatisch nach Score sortiert bleiben, liefert eine Abfrage der letzten Stunde einfach einen Bereichsfilter mit dem aktuellen Timestamp minus 3600 Sekunden als untere Grenze.

Fuer echte Zeitreihen-Workloads mit sehr hoher Schreibrate und komplexer Aggregation ist RedisTimeSeries als spezialisiertes Modul die bessere Wahl, aber fuer einfache Anwendungsfaelle wie Ereignisprotokolle, Rate-Limiting-Fenster oder das Speichern der letzten N Messwerte pro Sensor reicht ein Sorted Set vollkommen aus und spart eine zusaetzliche Abhaengigkeit. Mit ZREMRANGEBYSCORE lassen sich alte Eintraege ausserhalb eines Aufbewahrungsfensters periodisch entfernen, etwa alles aelter als 24 Stunden, was das Sorted Set effektiv als rollierenden Zeitreihen-Puffer nutzt.

Ein konkretes Beispiel ist ein Sliding-Window-Rate-Limiter: Jede Anfrage wird mit dem aktuellen Timestamp als Score in ein Sorted Set eingefuegt, veraltete Eintraege werden mit ZREMRANGEBYSCORE entfernt, und ZCARD liefert die Anzahl Anfragen im aktuellen Zeitfenster. Ueberschreitet diese Zahl das Limit, wird die Anfrage abgelehnt. Dieses Muster ist praeziser als ein simpler Fixed-Window-Zaehler, weil es Bursts an Fenstergrenzen korrekt beruecksichtigt.


# Time series with Sorted Sets: sliding-window rate limiter
redis-cli ZADD ratelimit:api:client99 1721742001 "req:1"
redis-cli ZADD ratelimit:api:client99 1721742003 "req:2"
redis-cli ZREMRANGEBYSCORE ratelimit:api:client99 -inf 1721741401
redis-cli ZCARD ratelimit:api:client99
redis-cli ZRANGEBYSCORE ratelimit:api:client99 1721741401 1721742060
redis-cli EXPIRE ratelimit:api:client99 60

5. Delayed Queues fuer verzoegerte Jobs

Ein weiterer praktischer Anwendungsfall von Sorted Sets ist die Delayed Queue: Jobs, die nicht sofort, sondern zu einem bestimmten Zeitpunkt in der Zukunft ausgefuehrt werden sollen. Der Score ist hier der geplante Ausfuehrungszeitpunkt als Unix-Timestamp, das Mitglied der serialisierte Job-Payload oder eine Job-ID. Ein Scheduler-Prozess fragt periodisch mit ZRANGEBYSCORE queue:delayed -inf LIMIT 0 10 alle faelligen Jobs ab und verschiebt sie mit ZREM gefolgt von LPUSH in eine sofort verarbeitbare Liste.

Der Vorteil gegenueber einer reinen Liste mit manueller Sortierung liegt darin, dass ZADD neue verzoegerte Jobs automatisch an der richtigen Position einsortiert, ohne dass die Anwendung selbst sortieren muss. Das macht Sorted Sets zur Grundlage vieler produktionsreifer Job-Scheduler, etwa fuer E-Mail-Erinnerungen, die 24 Stunden nach einer Aktion versendet werden sollen, oder fuer Retry-Logik, bei der ein fehlgeschlagener Job mit exponentiellem Backoff erneut eingeplant wird.

Fuer den atomaren Uebergang von der Delayed Queue in die Verarbeitung ist Vorsicht geboten: Zwischen dem Lesen faelliger Jobs und dem Entfernen aus dem Sorted Set koennen bei mehreren gleichzeitig laufenden Workern Race Conditions auftreten. Die robuste Loesung nutzt eine Lua-Skript-Transaktion oder ZPOPMIN mit anschliessender Score-Pruefung, sodass Lesen und Entfernen atomar in einem einzigen Redis-Command ablaufen.


# Delayed queue: schedule jobs for future execution
redis-cli ZADD queue:delayed 1721745600 "job:send-reminder:501"
redis-cli ZADD queue:delayed 1721749200 "job:retry-payment:88"
redis-cli ZRANGEBYSCORE queue:delayed -inf 1721745600 LIMIT 0 10
redis-cli ZREM queue:delayed "job:send-reminder:501"
redis-cli LPUSH queue:ready "job:send-reminder:501"

6. Priority-Queue-Pattern mit ZPOPMIN

Fuer Prioritaets-Warteschlangen, bei denen Jobs nicht nach Ankunftszeit, sondern nach Wichtigkeit verarbeitet werden sollen, ist der Score einfach die Prioritaetsstufe. Niedrigere Werte bedeuten hoehere Prioritaet, wenn ZPOPMIN verwendet wird, das atomar das Mitglied mit dem niedrigsten Score entfernt und zurueckgibt. Ein Worker ruft in einer Schleife ZPOPMIN queue:priority auf und erhaelt so immer den naechsten wichtigsten Job, ohne dass ein separater Sortiervorgang noetig ist.

Die Kombination aus mehreren Kriterien in einem einzigen Score, etwa Prioritaet multipliziert mit einem grossen Faktor plus Timestamp fuer Tie-Breaking, erlaubt es, komplexe Sortierlogik in eine einzige Fliesskommazahl zu kodieren. Ein Beispiel: score = priority_level * 1000000000 + timestamp sortiert primaer nach Prioritaet und bei gleicher Prioritaet nach Ankunftszeit, sodass die Queue innerhalb einer Prioritaetsstufe fair im First-In-First-Out-Prinzip arbeitet.

Fuer blockierendes Warten auf neue Prioritaets-Jobs gibt es BZPOPMIN, das analog zu BLPOP bei Listen einen Client blockiert, bis ein Element verfuegbar ist. Das vermeidet Polling und macht Sorted Sets zu einer vollwertigen Alternative zu dedizierten Message-Queue-Systemen fuer Szenarien mit moderatem Durchsatz, bei denen ohnehin schon eine Redis-Instanz im Einsatz ist.


# Priority queue: lower score = higher priority, atomic pop
redis-cli ZADD queue:priority 1 "job:critical-alert:1"
redis-cli ZADD queue:priority 5 "job:send-newsletter:2"
redis-cli ZADD queue:priority 1 "job:security-patch:3"
redis-cli ZPOPMIN queue:priority
redis-cli BZPOPMIN queue:priority 5
redis-cli ZRANGE queue:priority 0 -1 WITHSCORES

7. Leaderboards als Spezialfall richtig nutzen

Auch wenn dieser Beitrag den Fokus bewusst auf weniger offensichtliche Anwendungsfaelle legt, bleibt das klassische Leaderboard ein legitimer und haeufiger Einsatzzweck fuer Sorted Sets, und es lohnt sich, es kurz korrekt zu behandeln. Fuer ein Leaderboard mit Millionen Spielern liefert ZREVRANK die Platzierung eines einzelnen Spielers in logarithmischer Zeit, waehrend ZREVRANGE key 0 9 WITHSCORES die Top-10-Liste in einem einzigen Aufruf liefert.

Fuer Umgebungsansichten, etwa die fuenf Plaetze ueber und unter einem bestimmten Spieler, kombiniert man ZREVRANK zur Ermittlung der eigenen Position mit einem anschliessenden ZREVRANGE um diese Position herum. Diese Kombination ist deutlich effizienter als das Laden des kompletten Leaderboards und eine clientseitige Berechnung der Umgebung, besonders bei sehr grossen Spielerzahlen.

Mehrere separate Sorted Sets fuer unterschiedliche Zeitraeume, etwa ein taegliches, woechentliches und saisonales Leaderboard parallel, sind ein bewaehrtes Muster, um verschiedene Ranking-Ansichten anzubieten, ohne bei jeder Anfrage neu aggregieren zu muessen. Ein ZINCRBY beim Punktgewinn schreibt gleichzeitig in alle drei Sorted Sets, waehrend abgelaufene taegliche Leaderboards einfach per EXPIRE automatisch verschwinden, ohne manuelles Aufraeumen.

8. Performance: Skip List und Komplexitaet

Intern kombiniert Redis fuer Sorted Sets eine Skip List mit einer Hashtabelle. Die Skip List haelt die Mitglieder nach Score sortiert und ermoeglicht Bereichsabfragen in logarithmischer Zeit, waehrend die Hashtabelle den direkten Zugriff auf den Score eines bekannten Mitglieds in konstanter Zeit erlaubt. Diese Doppelstruktur erklaert, warum ZSCORE in O(1) laeuft, waehrend ZADD, ZRANK und ZRANGEBYSCORE mit O(log n) fuer die Positionierung in der sortierten Struktur zu Buche schlagen.

Fuer kleine Sorted Sets, analog zu Hashes und Sets, nutzt Redis das kompakte listpack-Encoding, gesteuert ueber zset-max-listpack-entries und zset-max-listpack-value. Erst beim Ueberschreiten dieser Schwellenwerte wechselt Redis zur vollen Skip-List-Implementierung. Operationen wie ZRANGEBYSCORE mit einem sehr grossen Ergebnisbereich sollten immer mit LIMIT begrenzt werden, um den Single-Threaded-Event-Loop nicht durch die Uebertragung tausender Elemente in einem einzigen Aufruf zu blockieren.

9. Sorted Set im Vergleich zu List und Set

Die Wahl zwischen Sorted Set, Liste und einfachem Set haengt davon ab, ob eine sortierbare Dimension existiert und wie auf die Daten zugegriffen werden muss. Die folgende Tabelle stellt die drei Strukturen fuer typische Warteschlangen- und Ranking-Anwendungsfaelle gegenueber.

Kriterium Liste Set Sorted Set
Eindeutigkeit Nein Ja Ja
Automatische Sortierung Nein Nein Ja, nach Score
Bereichsabfrage nach Wert Nicht sinnvoll Nicht moeglich O(log n) mit ZRANGEBYSCORE
Typischer Use Case FIFO-Queue, Feed Mitgliedschaft, Tags Ranking, Delayed Queue, Zeitreihe

Sorted Sets sind die richtige Wahl, sobald ein Element eine sortierbare Eigenschaft besitzt, nach der spaeter gefiltert oder iteriert werden soll. Listen bleiben die effizientere Wahl fuer reine Einfuege-Reihenfolge ohne Score-Semantik, und einfache Sets genuegen, wenn ausschliesslich die Mitgliedschaft relevant ist.

In der Praxis reicht ein Blick auf die geplanten Abfragen: Wird jemals nach einem Wertebereich gefiltert oder eine Rangfolge benoetigt, ist das Sorted Set fast immer die richtige Antwort unter den Redis-Datentypen.

Mironsoft

Redis-Warteschlangen, Scheduling und Ranking-Systeme

Delayed Jobs noch mit Cron statt mit Redis geplant?

Wir bauen Priority-Queues, Delayed-Job-Scheduler und Ranking-Systeme auf Basis von Sorted Sets, ohne zusaetzliche Message-Queue-Infrastruktur, inklusive Anbindung an bestehende Magento- und PHP-Systeme.

Queue-Design

Delayed Queues und Priority Queues mit Sorted Sets modellieren

Rate-Limiting

Sliding-Window-Limiter mit ZADD und ZREMRANGEBYSCORE aufbauen

Ranking-Systeme

Leaderboards mit ZREVRANK und ZREVRANGE performant umsetzen

10. Zusammenfassung

Redis Sorted Sets sind weit vielseitiger als das klassische Leaderboard-Beispiel vermuten laesst. Der Score ist einfach eine Fliesskommazahl, und je nachdem, was dieser Wert bedeutet, ergeben sich vollkommen unterschiedliche Anwendungsfaelle: Ein Unix-Timestamp macht das Sorted Set zu einem Zeitreihen-Speicher oder einer Delayed Queue, eine Prioritaetsstufe macht es zu einer Priority Queue mit ZPOPMIN, ein Punktestand macht es zum klassischen Ranking.

Die Skip-List-basierte interne Struktur garantiert logarithmische Zeit fuer Bereichsabfragen und Einfuegungen, waehrend die begleitende Hashtabelle den direkten Score-Zugriff in konstanter Zeit ermoeglicht. Wer diese Doppelnatur von Sorted Sets versteht, kann viele Probleme, die sonst eine dedizierte Message-Queue oder Zeitreihen-Datenbank erfordern wuerden, direkt mit der bereits vorhandenen Redis-Instanz loesen.

Redis Sorted Sets: Das Wichtigste auf einen Blick

Zeitreihen

Score als Timestamp, Bereichsabfragen mit ZRANGEBYSCORE, Bereinigung mit ZREMRANGEBYSCORE.

Delayed Queue

Score als geplanter Ausfuehrungszeitpunkt, faellige Jobs per ZRANGEBYSCORE -inf now.

Priority Queue

Score als Prioritaetsstufe, atomarer Pop mit ZPOPMIN oder blockierend mit BZPOPMIN.

Performance

Skip List sorgt fuer O(log n), ZSCORE via Hashtabelle fuer O(1).

11. FAQ: Redis Sorted Sets in der Praxis

1Set vs. Sorted Set?
Set garantiert keine Reihenfolge. Sorted Set haelt zusaetzlich einen Score und bleibt automatisch sortiert.
2Delayed Queue bauen?
Score als geplanter Timestamp. ZRANGEBYSCORE -inf now liefert faellige Jobs zur Verarbeitung.
3Was macht ZPOPMIN?
Entfernt und liefert atomar das Mitglied mit niedrigstem Score. Basis fuer Priority Queues.
4Fuer Zeitreihen geeignet?
Fuer einfache Faelle ja. Bei hoher Frequenz und Aggregation ist RedisTimeSeries besser geeignet.
5ZRANGE vs. ZRANGEBYSCORE?
ZRANGE filtert nach Rang, ZRANGEBYSCORE nach Score-Wert. Seit Redis 6.2 vereint ZRANGE mit BYSCORE beides.
6Mehrere Sortierkriterien?
In einen Score kodieren, etwa Prioritaet mal grosser Faktor plus Timestamp fuer Tie-Breaking.
7Komplexitaet von ZADD?
O(log n) durch die Skip List. ZSCORE dagegen O(1) via begleitender Hashtabelle.
8Race Conditions verhindern?
Lua-Skript-Transaktion oder ZPOPMIN mit Score-Pruefung, damit kein Job doppelt verarbeitet wird.
9ZADD auf existierendes Mitglied?
Score wird aktualisiert. Mit GT nur bei groesserem, mit LT nur bei kleinerem neuen Score.
10Wechsel zur vollen Skip List?
Gesteuert ueber zset-max-listpack-entries und -value. Kleine Sets bleiben im kompakten listpack.