How it works
The explanation, with examples you can run.
Pub/sub
# Terminal 1> SUBSCRIBE news1) "subscribe"2) "news"3) (integer) 1 # Terminal 2> PUBLISH news hello(integer) 1 # number of subscribers that received it # Terminal 1 receives1) "message"2) "news"3) "hello"PUBLISH returns how many subscribers got the message; with nobody subscribed it returns 0 and the message is gone. The Redis docs describe the delivery as at most once. A subscriber that disconnects, restarts, or falls too far behind (its output buffer overflows and Redis drops the connection) misses messages, with no way to replay them. Pub/sub suits signals where only the latest state matters: "config changed, reload", cache invalidation hints, live presence or typing indicators. Since Redis 7, sharded pub/sub (SSUBSCRIBE, SPUBLISH) keeps a channel's traffic on the shard that owns it in a cluster.
Streams
A stream is an append-only log. Each entry has an id (by default a millisecond timestamp and a sequence number) and a set of field-value pairs:
> XADD orders:events * type created order 1001"1760610000000-0"> XADD orders:events * type paid order 1001"1760610000001-0"(The ids depend on the clock when you run it.) Entries stay until you trim them, for example with XADD ... MAXLEN ~ 100000 or XTRIM, so a consumer that was offline can catch up. XREAD reads from any id, and can block waiting for new entries.
Consumer groups
To spread work across several workers and know what has been done, create a group:
> XGROUP CREATE orders:events billing 0OK> XREADGROUP GROUP billing worker-1 COUNT 10 STREAMS orders:events >1) 1) "orders:events" 2) 1) 1) "1760610000000-0" 2) 1) "type" 2) "created" ... 2) 1) "1760610000001-0" ...> XPENDING orders:events billing1) (integer) 2...> means "entries never delivered to this group". Each one goes to one consumer and is added to the group's pending entries list until the consumer runs XACK. If a worker crashes, its entries stay pending; another worker can take them over with XAUTOCLAIM (Redis 6.2 and later) once they have been idle long enough. That makes delivery at least once, so handlers must cope with seeing an entry twice. A second group, say analytics, reads the same entries independently.
Choosing
| Need | Use |
|---|---|
| Broadcast a hint; losing one is fine | Pub/sub |
| Every message processed, with retries | Stream with a consumer group |
| A simple work queue, no history | A list with LMOVE/BLMOVE to a processing list |
| Long retention, replay from weeks ago, very high volume | A log built for it, such as Kafka |
Streams live in memory like everything else in Redis, so trim them, and remember that their durability is Redis's: with asynchronous replication and periodic fsync, acknowledged entries can still be lost in a failover.
Check yourself
3 questions. Get them all right to finish this topic.
0 of 3 right so far. Get all three to finish this topic.