Skip to content

haxip-com/go-redis

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

40 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

GoRedis

CI codecov Go Report Card Go Version License

A lightweight, high-performance Redis-compatible server built from scratch in Go. Features a complete RESP2 protocol implementation, in-memory key-value storage with expiration, list data structures, and a distributed cluster mode with gossip-based node discovery. Zero dependencies on Redis source code or libraries.

Features

Cluster Mode (In Progress)

  • Gossip-based cluster protocol inspired by Redis Cluster
  • Hash tag support for co-locating related keys ({user:1}.name and {user:1}.email → same slot)
  • Binary message framing with length-prefixed gob encoding
  • Node roles (Master/Replica) and state machine (Online → PFail → Fail)
  • PING/PONG/MEET message types for heartbeat and node discovery
  • Epoch-based configuration versioning for consistency

Concurrency Model

  • Per-store sync.RWMutex for thread-safe concurrent reads and exclusive writes
  • Separate mutex for the TTL map to minimize lock contention
  • Each client connection handled in its own goroutine with configurable read/write timeouts

RESP Protocol Engine

  • Full implementation of the Redis Serialization Protocol (RESP2)
  • Supports all five RESP data types: Simple Strings, Errors, Integers, Bulk Strings, and Arrays
  • Inline command parsing for compatibility with tools like redis-cli and redis-benchmark
  • Custom serializer and deserializer with no third-party RESP dependencies

Command Support

Category Commands Description
Strings GET, SET Basic key-value operations
Counters INCR, DECR Atomic integer increment/decrement
Keys DEL, EXPIRE, EXPIREAT, TTL, PERSIST Key management and expiration
Lists LPUSH, RPUSH, LPOP, RPOP, LRANGE, LLEN Doubly-ended list operations with multi-element support
Server PING, ECHO, CONFIG Connection health and configuration

Key Expiration System

  • Dual eviction strategy matching Redis behavior:
    • Lazy expiration: keys checked on access and evicted if expired
    • Active expiration: background goroutine samples 20 random volatile keys every 100ms, continues if >25% are expired
  • Supports both relative TTL (EXPIRE) and absolute Unix timestamps (EXPIREAT)
  • NX, XX, GT, LT sub-options for conditional expiration

Interactive CLI Client

  • Built-in REPL client that connects to the server over TCP
  • Serializes user input into RESP and pretty-prints responses by type

Architecture

                    ┌──────────────────────────────────────────────┐
  redis-cli /       │              GoRedis Server                  │
  client binary     │                                              │
       │            │  ┌─────────────────────────────────────────┐ │
       │  TCP       │  │         connHandler (per goroutine)     │ │
       └───────────▶│  │                                         │ │
                    │  │  RESP Deserialize ──▶ commands map      │ │
                    │  │                      lookup + dispatch  │ │
                    │  └──────────────┬──────────────────────────┘ │
                    │                 │                            │
                    │                 ▼                            │
                    │  ┌──────────────────────────────┐            │
                    │  │            Store             │            │
                    │  │  ┌────────────┬────────────┐ │            │
                    │  │  │  Data Map  │  TTL Map   │ │            │
                    │  │  │ (RWMutex)  │ (RWMutex)  │ │            │
                    │  │  └────────────┴────────────┘ │            │
                    │  │         ▲                    │            │
                    │  │         │ active expire loop │            │
                    │  │         │                    │            │
                    │  └──────────────────────────────┘            │
                    │                 │                            │
                    │                 │ slot ownership check       │
                    │                 ▼                            │
                    │  ┌───────────────────────────────┐           │
                    │  │       ClusterState            │           │
                    │  │  Nodes · Slots[16384] · Epochs│           │
                    │  └──────────────┬────────────────┘           │
                    │                 │                            │
                    │                 ▼                            │
                    │  ┌──────────────────────────────┐            │
                    │  │   Cluster Bus                │            │
                    │  │   PING / PONG / MEET         │            │
                    │  │   Gossip · Failure Detection │            │
                    │  └──────────────────────────────┘            │
                    │                 ▲                            │
                    └─────────────────┼────────────────────────────┘
                                      │ TCP (binary, length-prefixed)
                                      ▼
                               Other GoRedis Nodes

Comparison with Redis

Feature Redis GoRedis
Protocol RESP2/RESP3 RESP2
Language C Go
Data types Strings, Lists, Sets, Sorted Sets, Hashes, Streams, etc. Strings, Lists
Persistence RDB + AOF In-memory only
Expiration Lazy + Active eviction Lazy + Active eviction (same strategy)
Cluster hashing CRC16 → 16384 slots CRC16 → 16384 slots (same algorithm)
Cluster gossip Binary protocol on port+10000 Gob-encoded protocol on port+10000
Hash tags {tag} support {tag} support
Replication Master-Replica with async replication Planned
Pub/Sub Full support Planned
Transactions MULTI/EXEC/WATCH Planned
Lua scripting Built-in Not planned
Threads Single-threaded event loop + I/O threads Goroutine-per-connection
Memory management Custom allocator (jemalloc) Go GC

Getting Started

Prerequisites

  • Go 1.25+ installed

Build and Run

# Clone the repository
git clone https://github.com/haxip-com/go-redis.git
cd go-redis

# Build the server
go build -o server ./src/server/

# Run the server (listens on port 6379)
./server

# In another terminal, build and run the CLI client
go build -o client ./src/client/
./client

Connect with redis-cli

GoRedis is wire-compatible with Redis, so you can use the official redis-cli:

redis-cli -p 6379

127.0.0.1:6379> SET hello world
OK
127.0.0.1:6379> GET hello
"world"
127.0.0.1:6379> LPUSH mylist a b c
(integer) 3
127.0.0.1:6379> LRANGE mylist 0 -1
1) "c"
2) "b"
3) "a"
127.0.0.1:6379> EXPIRE hello 60
(integer) 1
127.0.0.1:6379> TTL hello
(integer) 59

Run Tests

go test ./src/... -v -cover

Benchmark

redis-benchmark -p 6379 -t SET,GET -q

About

A lightweight Redis server implementation in Go.

Resources

License

Stars

Watchers

Forks

Contributors

Languages