Skip to main content
2024 Zig 0.14 TCP RESP2/RESP3 RDB

Redis Server (Zig)

From-scratch Redis-compatible server in Zig with RESP parsing, RDB persistence, and master-replica replication

Redis Server (Zig) screenshot

Overview

A from-scratch Redis server implementation in Zig 0.14 that handles the full lifecycle of a Redis-compatible key-value store: RESP2/RESP3 protocol parsing via a discriminated union (RespValue), a key-value store with millisecond-precision TTL expiration, complete RDB file format decoding and serialization, and master-replica replication with full handshake protocol and write propagation. Commands implemented: PING, ECHO, SET (with PX expiry), GET, CONFIG GET, KEYS, INFO, REPLCONF, PSYNC.

Architecture

Redis Server (Zig) architecture

Single-file 915-line implementation organized into clear logical sections: RESP protocol types (tagged union), recursive descent parser, stateful command executor, RDB binary format codec, master-slave handshake protocol, server state/config structs, and main with arg parsing and thread pool setup. The Executor struct bundles allocator, state, stream, and config to avoid threading 4 arguments through every command handler.

Code Highlights

RDB variable-length size decoding
fn rdbDecodeSize(reader: anytype) !u32 {
  const byte = try reader.readByte();
  const encoding = (byte & 0b11000000) >> 6;
  if (encoding == 0b00) {
    return byte & 0b00111111;
  } else if (encoding == 0b01) {
    const next = try reader.readByte();
    const short: u16 = @intCast(byte);
    return ((short & 0b00111111) << 6) + next;
  } else if (encoding == 0b10) {
    const b1: u32 = @intCast(try reader.readByte());
    const b2: u32 = @intCast(try reader.readByte());
    const b3: u32 = @intCast(try reader.readByte());
    const b4: u32 = @intCast(try reader.readByte());
    return (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;
  } else { return 0; }
}

Highlights

  • Implemented a complete Redis-compatible server from scratch in 915 lines of zero-dependency Zig with RESP protocol parser, key-value store with TTL, and RDB binary format codec
  • Designed a bidirectional binary format codec for Redis RDB persistence with variable-length size encoding (6/14/32-bit with 2-bit prefix discrimination)
  • Built a multi-threaded connection handler using Zig's stdlib thread pool -- 16 pre-spawned accept workers across 5 threads with lazy key expiration
  • Implemented the full Redis replication protocol -- handshake, RDB snapshot transfer, and real-time write propagation to connected replicas