Reading — step 1 of 3
Redis Streams
XADD & XREAD — Redis Streams
Pub/Sub is fire-and-forget — if no one's listening, messages vanish. Lists work as queues but lose history once consumed. Streams (added in Redis 5) are the missing piece: an append-only log that persists every entry, supports multiple consumers, and remembers what each consumer has seen.
This is Redis answering "what would Kafka look like, embedded?"
Data Model
A stream is an ordered sequence of entries. Each entry has:
- A monotonically increasing ID (
<milliseconds>-<sequence>, e.g.1700000000123-0) - A set of field/value pairs (like a hash)
events: [ id=1-0 {action: signup, user: alice} ]
[ id=2-0 {action: login, user: alice} ]
[ id=3-0 {action: signup, user: bob} ]
The ID is the cursor — readers say "give me everything after 2-0" and they get the new entries.
Core Commands
Write side:
XADD <stream> <id> field value [field value ...]— append entry.<id>can be*(auto-generate based on current time + counter) or explicit (123-0). Returns the assigned ID.XLEN <stream>— total entry count.
Read side:
XRANGE <stream> <start> <end>— historical slice.-= first,+= last. Returns all entries in range.XREAD COUNT <n> STREAMS <stream> <last_id>— read entries newer thanlast_id. Returns up tonentries.XREAD COUNT <n> BLOCK <ms> STREAMS <stream> $— blocking read for new entries (the$means "from the current end"). This is the pub/sub-like mode.
Consumer groups (advanced — not in this lesson):
XGROUP CREATE/XREADGROUP/XACK— multiple workers cooperatively process entries, like Kafka consumer groups.
ID Monotonicity
IDs must be strictly increasing. If you try XADD s 5-0 ... then XADD s 3-0 ..., you get:
-ERR The ID specified in XADD is equal or smaller than the target stream top item
This guarantee is what makes streams safe for replay: every consumer can rely on IDs as a strict total order.
Why Streams Beat Lists for Messaging
| Lists (LPUSH/BRPOP) | Streams | |
|---|---|---|
| Message persistence after consume | Lost | Retained |
| Multiple consumers see same msg | No (one wins) | Yes |
| Replay from arbitrary point | No | Yes |
| Built-in IDs | No | Yes |
| Range queries | No | Yes (XRANGE) |
| Consumer groups | No | Yes (XREADGROUP) |
Real-World Uses
- Event sourcing — append every domain event, derive read models by replay
- Activity feeds — Twitter-style timelines
- Job queues with audit trail — even after a job runs, the history is queryable
- CDC pipelines — capture changes from a primary store, downstream consumers replay
What You'll Build
XADD, XLEN, XRANGE, and a basic XREAD. Consumer groups are a follow-on you can layer on top once these primitives are in place.
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…