You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A high-performance, lightweight, in-memory Redis-compatible server built from the ground up using Java 25 and Netty. This project implements core Redis functionality with a focus on low latency, efficient memory usage, clean architecture, and production-grade replication.
✨ Features
Core Capabilities
⚡ High Performance: Built on Netty's asynchronous event-driven framework for massive concurrency
💾 In-Memory Storage: Optimized data structures using ConcurrentHashMap for thread-safe, lock-free reads
🔌 Redis Protocol (RESP): Full RESP implementation, compatible with any standard Redis client (redis-cli, jedis, lettuce, redis-py, etc.)
⏳ Advanced Expiration: Dual-strategy expiration (Lazy + Active background cleanup via DelayQueue)
🔄 Transaction Support: Full MULTI/EXEC/DISCARD support with optimized batch execution
📊 Pipelining: Full support for command pipelining with efficient batch processing
Replication (Master-Replica)
🔗 Master-Replica Architecture: Production-grade single-writer, log-based state machine
📡 Command Propagation: Automatic propagation with backpressure handling
🔄 Deterministic Replication: Commands are canonicalized before replication to ensure consistent state:
The exact command execution flow ensures consistency:
parse → validate → canonicalize → execute → append to log → send to replicas
Key principle: Replication is always downstream, never upstream.
Command Canonicalization
To ensure consistent state across master and replicas, commands are rewritten to their canonical (deterministic) form before propagation:
Original Command
Propagated Command
Reason
XADD stream * field value
XADD stream 1706745600000-0 field value
Auto-generated IDs depend on timestamp
SET key value EX 60
SET key value PXAT 1706745660000
Relative time → absolute timestamp
SET key value PX 5000
SET key value PXAT 1706745605000
Relative time → absolute timestamp
EXPIRE key 60
PEXPIREAT key 1706745660000
Relative seconds → absolute milliseconds
Full Sync vs Partial Sync Decision
When a replica connects, the master uses this decision logic:
Replica connects → sends replicationId + offset
│
▼
┌─────────────────────┐
│ ID matches master? │─── No ──▶ FULL SYNC
└─────────────────────┘
│ Yes
▼
┌─────────────────────┐
│ Offset in backlog? │─── No ──▶ FULL SYNC
└─────────────────────┘
│ Yes
▼
PARTIAL SYNC
No heuristics. No guessing. The decision is deterministic.
🧪 Testing
We maintain high confidence through comprehensive unit and integration tests.
# Run all tests (Unit + Integration)
./run_all_tests.sh
# Run only unit tests
mvn test# Run only integration tests
mvn verify -DskipUnitTests
# Run specific test class
mvn test -Dtest=CommandPropagatorTest
# Run with verbose output
mvn test -X
# Run replication-specific tests
mvn test -Dtest=MasterReplicaIntegrationTest
# Run scale/stress tests (benchmarks)
mvn test -Dtest=ReplicationScaleTest
# Run end-to-end replication test with actual servers
./test_replication.sh
# Run with stress test
./test_replication.sh --stress
# Run with multiple replicas
./test_replication.sh --scale
⚙️ Configuration
Command Line Arguments
java --enable-preview -jar target/redis-server.jar [options]
Options:
--port <port> Server port (default: 6379)
--replicaof <host><port> Start as replica of specified master
Configuration File
Edit src/main/resources/application.properties:
Property
Default
Description
redis.port
6379
Port to listen on
redis.boss.threads
1
Number of acceptor threads
redis.worker.threads
1
Number of I/O threads
redis.cleanup.interval.ms
5000
Expiry cleanup interval
redis.expiry.enabled
true
Enable/disable key expiration
redis.repl.backlog.size
1048576
Replication backlog size (1MB)
Environment Variables
Variable
Description
REDIS_PORT
Override server port
REDIS_EXPIRY_ENABLED
Override expiry setting
🔒 Production Considerations
Memory Management
Keys are stored in a ConcurrentHashMap with lazy expiration
Background cleanup prevents memory leaks from expired keys
Replication backlog is bounded (1MB default) with automatic eviction
Lists use LinkedList for O(1) push/pop operations
Streams use ConcurrentSkipListMap for efficient range queries
Thread Safety
All storage operations are atomic via compute() operations
Lock-free statistics using LongAdder (10x better than AtomicLong under contention)
Per-connection state isolation (no shared mutable state between connections)
Replication offsets tracked with AtomicLong for lock-free updates
Monitoring
INFO command provides comprehensive server statistics
INFO replication shows per-replica lag, offset, and health
Circuit breaker status and backpressure events tracked