Open-Source Wikis

/

Redis

/

Systems

/

Networking

redis/redis

Networking

Active contributors: antirez, Oran Agra, debing.sun, Yossi Gottlieb.

Purpose

The networking subsystem accepts TCP/Unix/TLS connections, parses RESP, dispatches commands, and writes replies back. It is the largest single chunk of code outside type implementations: src/networking.c is 5,783 lines and is on the hottest path of the server.

Source layout

File Role
src/networking.c Client lifecycle: accept, query buffer, RESP parsing, output buffers, addReply* helpers.
src/connection.c, src/connection.h Connection abstraction. connSocketType, connTLSType, connUnixType.
src/socket.c TCP/IPv4/IPv6 specifics.
src/unix.c Unix domain socket specifics.
src/tls.c OpenSSL-backed TLS. Plug-in implementation of connection.
src/anet.c, src/anet.h Low-level socket helpers (TCP, non-blocking I/O, getsockopt wrappers). Shared with redis-cli and redis-benchmark.
src/resp_parser.c, src/resp_parser.h RESP2 + RESP3 byte-level parser.
src/call_reply.c, src/call_reply.h Helpers for re-decoding a captured reply (used by modules and replication).
src/logreqres.c When built with LOG_REQ_RES, captures every command and reply for schema validation.

The client struct

struct client (declared in src/server.h, fields too numerous to list) is the runtime state for one connected peer. Notable fields:

Field Purpose
conn The connection* (TCP/Unix/TLS).
db Currently selected redisDb*.
argv, argc Parsed command arguments (an array of robj*).
cmd, lastcmd, realcmd The command being executed and the previous one.
reqtype RESP type currently being parsed (inline / multi-bulk).
multibulklen, bulklen Parser state — how many bulks remain, how big the next one is.
querybuf The SDS that holds bytes received from this client.
qb_pos The offset into querybuf consumed so far.
reply A list of clientReplyBlocks holding outgoing bytes.
bufpos, buf A small inline output buffer to avoid the list for short replies.
flags Bitmask of CLIENT_* flags (CLIENT_BLOCKED, CLIENT_PUBSUB, CLIENT_TRACKING, CLIENT_MULTI, …).
mstate If in MULTI, the queued commands.
bstate If blocked, the kind of block and resume info.
pubsub_* Subscribed channels/patterns, sharded channels.
tracking_* Tracked keys for client-side caching.
resp RESP version (2 or 3).
id Monotonic client id used by CLIENT KILL ID.

Clients are kept in server.clients (an adlist). Per-thread IO scratch lists are in server.io_threads_*. Replicas are in server.slaves. The master link client is server.master.

Accept path

sequenceDiagram
    participant Kernel
    participant Listener as listener fd
    participant Accept as acceptTcpHandler
    participant Client as struct client
    Kernel->>Listener: SYN
    Listener->>Accept: AE_READABLE
    Accept->>Kernel: accept(2)
    Kernel-->>Accept: connfd
    Accept->>Client: createClient(conn)
    Accept->>Client: connSetReadHandler(readQueryFromClient)
    Note over Client: client added to server.clients

For TLS, acceptTLSHandler does the same after wrapping the fd in an SSL object. For Unix sockets, acceptUnixHandler.

The number of listeners is configurable: TCP on bind addresses + port, optional TLS on tls-port, optional Unix on unixsocket. Each binds a separate listener fd and registers accept*Handler.

Read path

readQueryFromClient reads up to 16 KiB into the query buffer (chunked when IO threads are active to keep latency stable). Then processInputBuffer runs the RESP state machine:

while (c->qb_pos < sdslen(c->querybuf)) {
    if (!c->reqtype) {
        if (c->querybuf[c->qb_pos] == '*') c->reqtype = PROTO_REQ_MULTIBULK;
        else c->reqtype = PROTO_REQ_INLINE;
    }
    if (c->reqtype == PROTO_REQ_INLINE) {
        if (processInlineBuffer(c) != C_OK) break;
    } else {
        if (processMultibulkBuffer(c) != C_OK) break;
    }
    if (c->argc > 0) processCommandAndResetClient(c);
}

Inline parsing handles the legacy line-based protocol (SET foo bar\r\n). Multi-bulk parsing handles the standard RESP form (*3\r\n$3\r\nSET\r\n$3\r\nfoo\r\n$3\r\nbar\r\n).

processCommandAndResetClient calls processCommand (in src/server.c), which runs the ACL check, cluster slot check, command lookup, and dispatches to c->cmd->proc(c).

Write path

Command implementations call addReply* helpers. They write into either c->buf (the 16 KiB inline buffer) or append a clientReplyBlock to c->reply. The fd is then registered as writable, and writeToClient drains both buffers in beforeSleep.

The output-buffer-limit subsystem (client-output-buffer-limit normal/replica/pubsub) caps the total size of c->reply. If a client exceeds the soft or hard limit, the connection is closed asynchronously.

For replicas the same path applies, but with a much larger limit and special handling: replica writes carry replication offsets that are tracked separately so the master knows how far each replica has caught up.

RESP versions

HELLO 2 (default) speaks RESP2 — the historical protocol. HELLO 3 upgrades to RESP3, which adds:

  • Maps (%), sets (~), big numbers ((), doubles (,), booleans (#), null (_), verbatim strings (=), attributes (|), pushes (>).
  • Push frames so the server can deliver invalidation messages without the client polling.

The encoder helpers (addReplyMap, addReplySet, addReplyArrayLen, …) auto-select between RESP2 and RESP3 based on c->resp. Some commands have explicitly different reply shapes in the two protocols (e.g. HGETALL returns an array in RESP2 and a map in RESP3); those branches in their handlers.

The parser is in src/resp_parser.c and is shared with the Lua reply re-decoder.

Connection abstraction

struct connection (declared in src/connection.h) is a thin vtable that hides socket-vs-TLS differences:

struct ConnectionType {
    void (*ae_handler)(struct aeEventLoop *el, int fd, void *clientData, int mask);
    int (*connect)(struct connection *conn, const char *addr, int port, ...);
    int (*write)(struct connection *conn, const void *data, size_t len);
    int (*read)(struct connection *conn, void *buf, size_t len);
    int (*close)(struct connection *conn);
    int (*set_write_handler)(struct connection *conn, ConnectionCallbackFunc handler, int barrier);
    int (*set_read_handler)(struct connection *conn, ConnectionCallbackFunc handler);
    /* ... many more ... */
};

Three implementations:

  • socket in src/socket.c — TCP and IPv6.
  • unix in src/unix.c — Unix domain.
  • tls in src/tls.c — OpenSSL.

connTypeOfCluster returns the right type for the cluster bus (TLS or plain depending on tls-cluster).

TLS

src/tls.c implements the connection vtable using OpenSSL. It supports:

  • Server-side TLS (clients connect with --tls).
  • Client-side TLS for replication and cluster.
  • TLSv1.2 and TLSv1.3, configurable cipher list, OCSP stapling.
  • Optional client cert verification.
  • Optional tls-auth-clients for ACL+TLS hybrid authentication.

The TLS code can either be linked into redis-server (make BUILD_TLS=yes) or built as redis-tls.so (make BUILD_TLS=module) loaded with loadmodule. The module form is rare in production but is sometimes used in environments that ship a TLS-disabled binary by default.

Pub/Sub paths

The Pub/Sub state of a client (subscribed channels and patterns) lives on client. When a PUBLISH happens, the publisher's handler walks server.pubsub_channels (a dict of channel → list of subscribers) and calls addReplyPubsubMessage on each. Sharded Pub/Sub uses server.pubsubshard_channels and is per-slot; see Pub/Sub & tracking.

Where to start modifying

  • Add a connection type (e.g. QUIC) — implement the vtable in a new file, register it in src/connection.c's connTypeRegister* calls.
  • Tweak RESP parsingprocessMultibulkBuffer / processInlineBuffer in src/networking.c.
  • Change accept behaviouracceptTcpHandler, acceptUnixHandler, acceptTLSHandler near the top of src/networking.c.
  • Tune output buffer accountinggetClientOutputBufferMemoryUsage and the client-output-buffer-limit table in src/config.c.

Built by Factory AutoWiki from public repository content. It is a generated preview for codebase exploration, not source-maintained documentation.

Networking – Redis wiki | Factory