redis/redis
Pub/Sub & client tracking
Active contributors: antirez, Oran Agra, Madelyn Olson, debing.sun.
These two subsystems push asynchronous messages from the server to clients without those clients polling. Pub/Sub is the user-facing message broker; tracking is the engine for server-assisted client-side caching.
Source layout
| File | Role |
|---|---|
src/pubsub.c |
Pub/Sub: channels, patterns, sharded channels, PUBLISH/SUBSCRIBE/PSUBSCRIBE/SSUBSCRIBE. ~27 KB. |
src/notify.c |
Keyspace and key-event notifications (notify-keyspace-events). |
src/tracking.c |
Server-assisted client-side caching (CLIENT TRACKING). |
src/blocked.c |
Blocking commands (BLPOP, XREAD BLOCK, WAIT, …). |
src/timeout.c |
Per-blocked-client timeout sweeper. |
Pub/Sub
A PUBLISH chan msg walks server.pubsub_channels (a dict<sds, list<client*>>) and a list of pattern subscribers (server.pubsub_patterns). Each subscriber is sent a 3-element message frame: ["message", chan, msg] (or ["pmessage", pattern, chan, msg] for patterns).
There is no message queue, no acknowledgements, no replay. If a subscriber's output buffer overflows the client-output-buffer-limit pubsub, the connection is closed.
Channels and patterns
| Command | What it does |
|---|---|
SUBSCRIBE chan ... |
Subscribe to exact channel names. |
PSUBSCRIBE pat ... |
Subscribe to a glob pattern. |
UNSUBSCRIBE [chan ...], PUNSUBSCRIBE [pat ...] |
Stop. |
PUBLISH chan msg |
Send. |
PUBSUB CHANNELS [pattern] |
List channels with subscribers. |
PUBSUB NUMSUB [chan ...] |
Subscriber count per channel. |
PUBSUB NUMPAT |
Pattern-subscriber count. |
A subscribed client cannot run regular commands — its flags carry CLIENT_PUBSUB, and the dispatcher rejects most commands. The exceptions: SUBSCRIBE, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, SSUBSCRIBE, SUNSUBSCRIBE, PING, QUIT, RESET.
Sharded Pub/Sub
Sharded Pub/Sub (SPUBLISH, SSUBSCRIBE, SUNSUBSCRIBE) delivers messages only within the cluster shard that owns the channel's slot. The slot is computed the same way as for keys (CRC16(channel) % 16384).
- Reduces fan-out cost in clusters.
- Keeps message volume on the local shard's bus.
- Subscribers on other shards never see the message.
The implementation lives in src/pubsub.c alongside the regular code, but the dispatch consults the cluster's slot owner to refuse cross-shard publishes.
Replication
Pub/Sub messages are not replicated. Replicas don't see the publish stream. This was a deliberate design choice — Pub/Sub's semantics are "fire and forget" and replication adds nothing.
The cluster bus, on the other hand, propagates regular Pub/Sub messages between nodes when a subscriber on a different node has matching subscriptions. Sharded Pub/Sub doesn't propagate.
Keyspace notifications
notify-keyspace-events <flags> enables Pub/Sub messages on data mutations:
__keyspace@<dbid>__:<key>channel emits the event name (e.g.del,expired,set).__keyevent@<dbid>__:<event>channel emits the key that experienced the event.
Flag letters select event categories: K (keyspace), E (keyevent), g (generic — del, expire, rename), $ (string), l (list), s (set), h (hash), z (zset), x (expired), e (evicted), t (stream), d (module), m (key-miss), A (alias for g$lshzxe).
The implementation is notifyKeyspaceEvent in src/notify.c. Callers in the type implementations invoke it after a successful mutation:
notifyKeyspaceEvent(NOTIFY_GENERIC, "del", c->argv[1], c->db->id);Client tracking
Client-side caching (CLIENT TRACKING ON/OFF) lets a client cache the values of keys it has fetched, with the server proactively pushing an "invalidation" message when a key changes. The client doesn't need to TTL its cache or poll — it follows the server's signal.
There are two modes:
- Default mode — the server tracks per-key per-client which clients have read which keys. On mutation, every interested client receives an invalidation.
- Broadcast mode (
BCAST) — the client subscribes to one or more prefix patterns (PREFIX user:); whenever any key matching a prefix changes, every BCAST subscriber for that prefix is notified. No per-key bookkeeping.
The invalidation message arrives on a separate connection identified by CLIENT TRACKING ON REDIRECT <client-id> (RESP2 mode), or as an inline RESP3 push frame.
src/tracking.c implements both modes, the prefix table, and the per-key inverted index (server.tracking_table).
CLIENT TRACKINGINFO returns the current tracking state.
Blocking commands
BLPOP, BRPOP, BLMPOP, BLMOVE, BRPOPLPUSH, BZPOPMIN, BZPOPMAX, BZMPOP, XREAD BLOCK, XREADGROUP BLOCK, WAIT, WAITAOF, SUBSCRIBE-state, MIGRATE and a few module-defined commands all block the client until either:
- The condition that the command is waiting for becomes true (a list gets pushed to, a stream gets a new entry, a replica catches up).
- A timeout fires (per-command argument or default).
The implementation uses a blocked client state on client.bstate. The blocking command sets the state, returns from the handler without sending a reply, and the cron scans periodically. When the condition is met (e.g. a new LPUSH arrives), the producer's command path calls into signalKeyAsReady and the blocked client is unblocked, the original command re-run on the main thread.
src/blocked.c holds the lifecycle: blockClient, unblockClient, processUnblockedClients, the per-key wait list. src/timeout.c runs the per-block timeout sweeper.
Where to start modifying
- Add a Pub/Sub variant — the dispatch in
subscribeCommand/publishCommandis a small switch insrc/pubsub.c. - Add a keyspace event letter — extend the
NOTIFY_*flags insrc/server.hand the parser inkeyspaceEventsFlagsToString/StringToFlagsinsrc/notify.c. - Tighten tracking memory —
tracking-table-max-keyscaps the inverted index size; the eviction policy is intrackingRememberKeys. - Implement a blocking command — the canonical pattern is
blockForKeysfollowed byreplyToBlockedClientTimedOutand aserveClientBlockedOnList-style ready callback.
Related pages
- Networking — clients carry the Pub/Sub state.
- Modules —
RedisModule_BlockClientis the blocking-command primitive for modules. - Cluster — sharded Pub/Sub is cluster-aware.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.