A high-performance, thread-safe Redis server implementation built from scratch in Java.
- Connection Management:
PING- Test server connectivity - Configuration:
CONFIG GET <param>- Retrieve server configuration parameters (dir,dbfilename)
- Role Management:
REPLICAOF NO ONE- Switch server to master role
- Persistence:
SAVE- Perform a synchronous save of the dataset to an RDB file
- String Operations:
SET key value [PX milliseconds]- Store key-value pairs with optional expiryGET key- Retrieve values by keyECHO message- Echo back messages
- List Operations:
RPUSH key element [element ...]- Add elements to the right of a listLPUSH key element [element ...]- Add elements to the left of a listLPOP key [count]- Remove and return elements from the left of a listBLPOP key timeout- Blocking left pop with timeout supportLRANGE key start stop- Get a range of elements from a listLLEN key- Get the length of a list
- Stream Operations:
XADD key id field value [field value ...]- Add entries to a streamXRANGE key start end- Get a range of entries from a streamXREAD [BLOCK timeout] streams key1 [key2 ...] id1 [id2 ...]- Read new entries from one or more streams, optionally blocking
- Key Operations:
TYPE key- Check the data type of a key (returns: string, list, stream, or none)KEYS *- List all keys in the databaseINCR key- Increment the integer value of a key by 1
- Server Information:
INFO replication- Get information about replication status
- Transaction Support:
MULTI- Start a transaction blockEXEC- Execute all queued commands in the transactionDISCARD- Discard all queued commands in the transaction
- Replication: Master-replica support with command propagation and full resynchronization
- RDB Persistence: Loads data from RDB files at startup (
--dirand--dbfilenameflags supported). Supports parsing multiple keys, string values, and expiry times from RDB files. - Expiry Support: Automatic key expiration with millisecond precision
- Blocking Operations: BLPOP and XREAD BLOCK with configurable timeouts and FIFO client ordering
- Thread Safety: Concurrent client handling with proper synchronization
- Java 8 or higher (Java 23+ recommended)
- Maven 3.6 or higher
-
Clone the repository
-
Start the project:
./server.shThe server will start on localhost:6379 by default.
# Connect using redis-cli or any Redis client
redis-cli -p 6379
# Test connectivity
> PING
PONG
# String operations
> SET mykey "Hello World"
OK
> GET mykey
"Hello World"
# Set with expiry (in milliseconds)
> SET temp_key "expires soon" PX 5000
OK
# List operations
> RPUSH mylist "first" "second" "third"
(integer) 3
> LRANGE mylist 0 -1
1) "first"
2) "second"
3) "third"
# Blocking operations
> BLPOP mylist 10
1) "mylist"
2) "first"
# Stream operations
> XADD stream_key 1526919030474-0 temperature 36 humidity 95
"1526919030474-0"
> XADD stream_key * foo bar
# Note: When you use redis-cli in shell, you should type "*" instead of *.
# If you use *, The shell is expanding the * wildcard to match all files in your current directory.
# This is a shell expansion issue, not a problem with my code. The * is being interpreted by shell before it reaches redis-cli
> XRANGE mystream - +
1) 1) "1680000000000-0"
2) 1) "field1"
2) "value1"
> XREAD BLOCK 5 streams mystream 0-0
1) 1) "mystream"
2) 1) 1) "1680000000000-0"
2) 1) "field1"
2) "value1"
# Transaction operations
> MULTI
OK
> SET key1 "value1"
QUEUED
> RPUSH mylist "item"
QUEUED
> EXEC
1) OK
2) (integer) 1This server supports Redis master-replica replication.
Option 1:
./server.sh --port 6380 --replicaof "localhost 6379"Option 2:
./server.sh --port 6380 --replicaof 127.0.0.1 6379The replica will connect to the master, perform the handshake, and receive command propagation.
This server supports loading data from Redis RDB files at startup.
Example:
./server.sh --dir /path/to/rdb/dir --dbfilename dump.rdbAfter loading, all keys and values from the RDB file are available for GET, KEYS *, and other commands.
Note: Currently, my Redis Clone only Supports reading String data type from RDB files.
This project includes a comprehensive test suite using JUnit 5 to ensure reliability and correctness.
# Run all tests
mvn test
# Run tests quietly (less verbose output)
mvn test -q
# Run a specific test class
mvn test -Dtest=StringStorageTest
# Run tests with coverage
mvn clean testTest files are located in src/test/java/. To add new tests:
- Create a test class in the appropriate package under
src/test/java/ - Use JUnit 5 annotations (
@Test,@BeforeEach,@DisplayName) - Follow the existing test patterns in
StringStorageTest.java - Run
mvn testto verify your tests pass
Planned test coverage for:
- Stream Operations (XADD, XRANGE, XREAD with blocking)
- Replication (Master-replica sync, command propagation)
- RDB Persistence (Loading, saving, expiry handling)
- Enhanced
REPLICAOFcommand: allow dynamic switching between master and replica roles - Full sync: enable replicas to receive and load real RDB files from master
This project is implemented following the tutorial from Codecrafters Build Your Own Redis. Special thanks to the Codecrafters team for their excellent resources and guidance.