redis/redis
RESP protocol
The Redis Serialization Protocol. The wire format spoken over TCP/Unix/TLS by clients and replicas.
Versions
| Version | Year | Status |
|---|---|---|
| RESP2 | Original (Redis 2.0) | The default. Every client speaks RESP2. |
| RESP3 | Redis 6.0 (May 2020) | Opt-in via HELLO 3. Adds richer types and push frames. |
A connection always starts in RESP2. The HELLO command upgrades:
HELLO 3
HELLO 3 AUTH user pass
HELLO 3 AUTH user pass SETNAME myclientThe reply to HELLO is a map of server attributes (server, version, proto, id, mode, role, modules).
Source
src/resp_parser.c,src/resp_parser.h— the byte-level parser used by Lua reply re-decoding and tests.src/networking.c— the production-path parser (processInlineBuffer,processMultibulkBuffer) and the encoder helpers (addReply*).src/call_reply.c,src/call_reply.h— represents a fully-decoded reply for capture/replay purposes.
Type bytes
Each reply begins with a single byte indicating its type:
| Byte | Type | RESP version | Notes |
|---|---|---|---|
+ |
Simple string | 2, 3 | +OK\r\n |
- |
Error | 2, 3 | -ERR foo\r\n |
: |
Integer | 2, 3 | :42\r\n |
$ |
Bulk string | 2, 3 | $3\r\nfoo\r\n (length then payload) |
* |
Array | 2, 3 | *3\r\n... (count then elements) |
_ |
Null | 3 | _\r\n |
, |
Double | 3 | ,3.14\r\n |
( |
Big number | 3 | (3492890328409238509324850943850943825024385\r\n |
# |
Boolean | 3 | #t\r\n or #f\r\n |
= |
Verbatim string | 3 | Type-tagged bulk: =15\r\ntxt:Some string\r\n |
% |
Map | 3 | %2\r\n then alternating key/value frames |
~ |
Set | 3 | ~3\r\n then elements |
> |
Push | 3 | Out-of-band notification; first element is the type (pubsub, invalidate, monitor, …) |
| |
Attribute | 3 | Optional metadata preceding the next reply |
RESP2 fallbacks
Where RESP3 has a richer type, RESP2 falls back as follows:
| RESP3 | RESP2 |
|---|---|
_ (null) |
$-1\r\n (null bulk) or *-1\r\n (null array) |
# (boolean) |
:0 or :1 |
, (double) |
bulk string of the formatted number |
( (big num) |
bulk string |
% (map) |
flat array of alternating key/value |
~ (set) |
array |
> (push) |
normal multi-bulk (RESP2 doesn't have out-of-band) |
Most clients negotiate RESP2 by default and only opt into RESP3 when they need maps or push frames (e.g. server-assisted client-side caching).
Request format
Two valid client-to-server formats:
- Inline — a single line with space-separated tokens:
SET foo bar\r\n. Used mostly by interactive use andredis-cli. The parser isprocessInlineBuffer. - Multi-bulk — the canonical RESP form:
*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n. The parser isprocessMultibulkBuffer.
Modern clients always use multi-bulk because it handles binary-safe arguments correctly.
Pipelining
Multiple requests can be sent before reading replies. The server processes them in order; each command's reply is emitted in the same order. There is no framing overhead.
redis-benchmark -P n uses pipelining to amortise network round-trips.
Server-pushed messages
In RESP3, the server can push messages to the client at any time using the > push frame:
pubsubpush — when a client is subscribed and a message arrives.invalidatepush — when a watched key changes andCLIENT TRACKINGis on.monitorpush — whenMONITORis active.
Push frames don't count as command replies, so a pipelined reader has to demultiplex them on its own. RESP2 doesn't have push frames; the equivalents are delivered over a separate connection or as in-line replies that the client must recognise.
Errors
Error replies start with -. The first space-delimited token is the error class:
| Class | Meaning |
|---|---|
ERR |
Generic command error. |
WRONGTYPE |
Wrong data type for the command. |
MOVED |
Cluster: this slot lives elsewhere. |
ASK |
Cluster: this slot is migrating; redirect for this single command. |
LOADING |
The server is loading a dataset and can't serve. |
NOSCRIPT |
EVALSHA for a script not in the cache. |
BUSY |
A script or function is running. Use SCRIPT KILL. |
MASTERDOWN |
A replica's master is down. |
READONLY |
A replica refusing a write. |
MISCONF |
Persistence is mis-configured (e.g. RDB save is failing). |
OOM |
Out of memory and policy is noeviction. |
NOAUTH |
Authentication required. |
WRONGPASS |
Authentication failed. |
NOPERM |
ACL denied. |
EXECABORT |
A MULTI/EXEC block was aborted because of a queued-command error. |
CROSSSLOT |
Cluster: keys span multiple slots. |
TRYAGAIN |
Cluster: some keys are migrating; retry. |
MASTERDOWN |
Replica writes refused because master link is down. |
BUSYKEY |
COPY ... REPLACE would overwrite. |
The full list is the table at the top of src/server.h near the shared errors.
Inline commands
Inline commands are handy when you ssh into the server and nc localhost 6379:
PING
+PONG
SET hello world
+OK
GET hello
$5
worldThe server's parser detects "this looks like text, not a * count" and switches to inline mode.
Where to start modifying
- Add a RESP3 type — extend the encoder helpers in
src/networking.c(addReply*family). Update the parser insrc/resp_parser.c. - New error class — add a shared object in
src/server.c'screateSharedObjectsand use it viaaddReply(c, shared.<name>). - Tweak inline parsing —
processInlineBufferinsrc/networking.c.
Related pages
- Networking — the parser and emitters.
- Pub/Sub & tracking — RESP3 push frames carry invalidations and pub/sub.
Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.