Skip to content
Sarcastic-SoulPublic

About

Redis-compatible in-memory database built from scratch in Java — custom RESP2/RESP3 protocol, NIO event loop, replication, AOF/RDB persistence, and pub/sub. ~165K req/sec, compatible with redis-cli.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Radish — Redis-Compatible In-Memory Server in Java

A fast, lightweight, RESP2/RESP3-compatible in-memory Redis server built entirely in Java from scratch — no external dependencies. Connect to it with redis-cli or any standard Redis client library.

Demo

demo.mp4

Architecture Radish Architecture


🚀 Quick Start

See docs/COMMANDS.md for the full list of supported commands (Strings, Lists, Hashes, Sets, Sorted Sets, Pub/Sub, Transactions, RESP3, Replication, RDB, etc.). See docs/design_decisions.md for deep-dive technical design rationale, JVM vs C Redis architecture trade-offs, and systems decisions.

Prerequisites

  • Java 17+ (or Docker)

Build & Run

rm -rf out && mkdir -p out
find src -name "*.java" | xargs javac -d out

# Start the server (using default radish.conf)
java -cp out com.radish.Main radish.conf

# In a new terminal, start the custom interactive CLI
java -cp out com.radish.Main cli

Run with Docker / Docker Compose

# Multi-node Leader + Replica cluster
docker-compose up --build

⚡ Performance & Benchmarks

Radish uses a non-blocking Java NIO architecture built on Selector, ServerSocketChannel, and ByteBuffer, following an event-driven design similar to Redis. This allows a single event loop to efficiently handle many concurrent client connections while minimizing thread context-switching overhead.

Benchmarks were executed locally using:

redis-benchmark -c 50 -n 100000 -q
Command Throughput Median Latency (p50)
PING ~151,000 req/s 0.151 ms
SET ~144,000 req/s 0.151 ms
GET ~175,000 req/s 0.151 ms
HSET ~164,000 req/s 0.151 ms
LPUSH ~159,000 req/s 0.151 ms

Benchmark Configuration

  • Localhost benchmark
  • 50 concurrent clients
  • 100,000 total requests
  • Full Features Enabled: everysec AOF Background Sync, RDB Snapshotting, Probabilistic Expiry, and Approximated LRU.
  • Java NIO event loop

Memory & System Footprint

Metric Value
Concurrent Clients 50
Requests 100,000
Peak Memory ~24 MB
Average Latency 0.17 ms
Median Latency 0.15 ms
Aggregate Throughput ~165,000 req/s

The ~165K req/sec figure is the aggregate throughput across the full redis-benchmark -c 50 -n 100000 -q run (all command types combined); per-command breakdowns range from ~144K (SET) to ~175K (GET) req/sec, as shown above.

Comparison with Redis

Benchmarks performed on the same machine to contrast Radish (Pure Java) against the industry-standard Redis (C).

Metric Radish (Java) Redis (C)
PING 151k req/s 210k req/s
GET 175k req/s 220k req/s
SET 144k req/s 205k req/s

While Redis remains faster due to its highly optimized C implementation, Radish demonstrates comparable architecture and achieves extremely high throughput using pure Java and Java NIO, even with full disk durability and memory eviction enabled.


🔄 Leader-Follower Replication (REPLICAOF)

Radish supports full Leader-Follower replication with multi-stage handshakes, binary RDB resync, and real-time command streaming:

# Connect to Follower server and replicate Leader on port 6389:
redis-cli -p 6390 REPLICAOF 127.0.0.1 6389

# Promote Follower to standalone primary:
redis-cli -p 6390 REPLICAOF NO ONE
  • Full Resync: Follower requests PSYNC, Leader streams snapshot payload.
  • Live Stream: Mutating write commands (SET, INCR, LPUSH, DEL) stream over non-blocking socket channels in real-time.

💾 Dual Persistence (AOF + RDB)

  1. RDB Binary Snapshotting (SAVE / BGSAVE):
    • Compact binary snapshots (dump.rdb) featuring type tags and 8-byte millisecond expiration tags.
    • Non-blocking BGSAVE executes snapshotting asynchronously in a background thread.
  2. AOF Log Write-Through (radish.aof):
    • Every mutating command is written to an AOF buffer and flushed every second (everysec).
    • BGREWRITEAOF compacts command history into minimal dataset recovery commands.
  3. Hybrid Startup Boot:
    • Radish automatically loads dump.rdb baseline and replays remaining radish.aof delta commands on startup.

🌐 RESP3 Protocol Support (HELLO 3)

Clients can negotiate protocol version 3 via HELLO 3:

  • RESP3 Native Types: Map (%), Set (~), Double (,), Boolean (#), Null (_), Push (>).
  • Dynamic Dual-Mode Encoding: Serves RESP3 native types when negotiated, or backward-compatible RESP2 array fallbacks.

💻 Custom CLI

Radish comes with a built-in interactive CLI client featuring:

  • Colorized Formatting: Arrays, integers, strings, and errors are color-coded for readability.
  • Session History: Type history to view past commands, and !N to re-execute them.
  • Watch Mode: watch 2 DBSIZE clears the screen and runs the command every 2 seconds.

🌐 HTTP Admin API & Web Dashboard

Running on port 6380 while the server is active. Open http://localhost:6380 in your browser for a live web dashboard showing server statistics, memory usage, and keyspace contents.


🗺️ Project Structure

src/main/java/com/radish/
├── Main.java                      # Server & CLI entry point
├── config/
│   ├── ServerConfig.java          # Configuration properties
│   └── ConfigFileParser.java      # redis.conf style parser
├── server/
│   ├── RadishServer.java          # NIO Selector Event Loop
│   ├── NioSession.java            # Non-blocking stateful connection buffers
│   ├── ConnectionManager.java     # Active connections tracker
│   └── ActiveExpiryDaemon.java    # Probabilistic background sweeper
├── replication/
│   └── ReplicationManager.java    # Leader/Replica state, RDB stream & broadcast
├── protocol/
│   ├── RespParser.java            # RESP2/RESP3 zero-copy parser with ProtocolException
│   ├── RespEncoder.java           # Dual-mode RESP2/RESP3 wire encoder
│   ├── RespCommand.java           # Parsed command DTO
│   ├── RespMap.java               # RESP3 Map wrapper (%)
│   ├── RespSet.java               # RESP3 Set wrapper (~)
│   └── RespPush.java              # RESP3 Push wrapper (>)
├── command/                       # Command Handlers
│   ├── CommandDispatcher.java     # Routing, AOF write-through & replication streaming
│   ├── ReplicaOfCommand.java      # REPLICAOF / SLAVEOF
│   ├── PsyncCommand.java          # PSYNC / SYNC
│   ├── HelloCommand.java          # HELLO (RESP3 negotiation)
│   ├── SaveCommand.java           # SAVE
│   ├── BgsaveCommand.java         # BGSAVE
│   └── ...                        # (35+ command handlers)
├── persistence/
│   ├── RdbWriter.java             # Binary snapshot serializer
│   ├── RdbLoader.java             # Binary snapshot deserializer
│   ├── AofWriter.java             # Background AOF queue + fsync
│   └── AofLoader.java             # MappedByteBuffer AOF replay
├── storage/
│   ├── InMemoryStorage.java       # ConcurrentHashMap engine + SCAN + WATCH touch
│   └── ScanResult.java            # SCAN cursor pagination DTO
├── transaction/
│   ├── TransactionState.java      # MULTI/EXEC/WATCH transaction state
│   └── WatchManager.java          # Optimistic key locking manager
├── test/                          # Comprehensive Test Suites
│   ├── RespParserUnitTest.java    # Parser unit tests
│   ├── CommandHandlerUnitTest.java# Isolated handler unit tests
│   ├── ConfigFileParserTest.java  # Config file tests
│   ├── FuzzTest.java              # 150,000+ fuzzing & bit-flip iterations
│   ├── Resp3Test.java             # RESP3 protocol tests
│   ├── ReplicationTest.java       # Leader-Follower integration tests
│   ├── RdbPersistenceTest.java    # RDB persistence tests
│   ├── ConcurrencyTest.java       # Multi-threaded safety tests
│   └── StressTest.java            # High-throughput benchmark suite
└── http/
    └── AdminHttpServer.java       # Embedded JSON API & Web Dashboard on port 6380

About

Redis-compatible in-memory database built from scratch in Java — custom RESP2/RESP3 protocol, NIO event loop, replication, AOF/RDB persistence, and pub/sub. ~165K req/sec, compatible with redis-cli.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Contributors

Languages