Protocol Design Philosophy
RESP was designed with the following goals:- Simple to implement in any programming language
- Fast to parse without complex state machines
- Human-readable for debugging with tools like
telnetornc - Support for multiple data types
- Efficient binary-safe string transmission
RESP Data Types
RESP defines several data type indicators, each represented by the first byte:Simple Strings
Simple strings are non-binary-safe strings that cannot contain\r or \n characters. They begin with + and end with \r\n.
\r after the + prefix, extracts the string between them, and advances past the trailing \r\n (resp_parser.c:61-66).
Errors
Errors are similar to simple strings but use- as the first byte. By convention, the error message starts with an error code in uppercase.
- and \r\n (resp_parser.c:69-74).
Integers
Integers are sent with: as the first byte, followed by the string representation of the number.
long long value using string2ll() (resp_parser.c:77-84).
Bulk Strings
Bulk strings are binary-safe and can contain any data. The format is$<length>\r\n<data>\r\n.
$-1\r\n represents a null bulk string:
\r\n. For null bulk strings (length = -1), a special null callback is invoked (resp_parser.c:42-58).
Arrays
Arrays are composite types that can contain multiple elements of any RESP type. The format is*<count>\r\n followed by the elements.
parseReply() recursively for each element (resp_parser.c:153-165).
Null arrays are a RESP2 concept. In RESP3, use the null type
_\r\n instead. The server maintains backward compatibility by sending *-1\r\n to RESP2 clients (networking.c:1210-1213).Complete Protocol Example
Here’s a raw protocol communication example for the commandSET mykey myvalue:
Client sends:
*3\r\n- Array with 3 elements$3\r\nSET\r\n- Bulk string “SET” (3 bytes)$5\r\nmykey\r\n- Bulk string “mykey” (5 bytes)$7\r\nmyvalue\r\n- Bulk string “myvalue” (7 bytes)
RESP2 vs RESP3
Redis supports both RESP2 and RESP3 protocols. By default, clients connect using RESP2. RESP3 introduces additional data types including maps, sets, booleans, doubles, big numbers, and push messages.
RESP3 Additional Types
RESP3 adds several new types while maintaining backward compatibility: Null:_\r\n - Universal null type
Boolean: #t\r\n (true) or #f\r\n (false)
Double: ,<floating-point-number>\r\n
(<big-number>\r\n
%<count>\r\n followed by key-value pairs
~<count>\r\n followed by elements
Protocol Version Selection
Clients can select the protocol version using theHELLO command:
c->resp field, networking.c:147). This determines how the server formats responses.
Protocol Constants
The implementation defines several important constants (server.h:188-193):PROTO_INLINE_MAX_SIZE(64KB) - Maximum size for inline protocol requestsPROTO_REPLY_CHUNK_BYTES(16KB) - Default output buffer chunk sizePROTO_IOBUF_LEN(16KB) - Generic I/O buffer sizePROTO_MBULK_BIG_ARG(32KB) - Threshold for large multi-bulk arguments
Inline Commands
For simplicity, Redis also supports an inline command format for simple use cases liketelnet. Commands are sent as space-separated arguments followed by \r\n:
*, RESP multi-bulk parsing is used; otherwise, inline parsing is used (networking.c:2942-3048).
Error Handling
Protocol errors result in the client being marked for disconnection. Common protocol errors include:- Invalid multi-bulk count
- Missing
\r\nterminators - Bulk string length mismatches
- Invalid type indicators
CLIENT_CLOSE_AFTER_REPLY flag (networking.c:3054-3085).
Performance Optimizations
The protocol implementation includes several optimizations:-
Shared Objects: Common responses like
:0\r\n,:1\r\n, and small bulk/array headers are pre-allocated as shared objects (networking.c:1122-1133) - Direct Buffer Writes: For simple responses, the server writes directly to the client’s output buffer without allocation (networking.c:447-466)
- Zero-Copy: Large bulk strings can use reference counting to avoid copying data (networking.c:1230-1264)
-
Efficient Parsing: The parser uses
strchr()andmemchr()for fast line scanning rather than byte-by-byte parsing