Skip to content

Andy2887/JRedis

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

93 Commits
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Redis Clone in Java

A high-performance, thread-safe Redis server implementation built from scratch in Java.

🚀 Features

Core Commands

  • 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 expiry
    • GET key - Retrieve values by key
    • ECHO message - Echo back messages
  • List Operations:
    • RPUSH key element [element ...] - Add elements to the right of a list
    • LPUSH key element [element ...] - Add elements to the left of a list
    • LPOP key [count] - Remove and return elements from the left of a list
    • BLPOP key timeout - Blocking left pop with timeout support
    • LRANGE key start stop - Get a range of elements from a list
    • LLEN key - Get the length of a list
  • Stream Operations:
    • XADD key id field value [field value ...] - Add entries to a stream
    • XRANGE key start end - Get a range of entries from a stream
    • XREAD [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 database
    • INCR 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 block
    • EXEC - Execute all queued commands in the transaction
    • DISCARD - Discard all queued commands in the transaction

Advanced Features

  • Replication: Master-replica support with command propagation and full resynchronization
  • RDB Persistence: Loads data from RDB files at startup (--dir and --dbfilename flags 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

🛠️ Setup and Installation

Prerequisites

  • Java 8 or higher (Java 23+ recommended)
  • Maven 3.6 or higher

Installation

  1. Clone the repository

  2. Start the project:

./server.sh

The server will start on localhost:6379 by default.

📖 Basic Operations

# 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) 1

🪞 Replication

This server supports Redis master-replica replication.

Start a replica with:

Option 1:

./server.sh --port 6380 --replicaof "localhost 6379"

Option 2:

./server.sh --port 6380 --replicaof 127.0.0.1 6379

The replica will connect to the master, perform the handshake, and receive command propagation.

💾 RDB Persistence

This server supports loading data from Redis RDB files at startup.

Example:

./server.sh --dir /path/to/rdb/dir --dbfilename dump.rdb

After 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.

🧪 Testing

This project includes a comprehensive test suite using JUnit 5 to ensure reliability and correctness.

Running Tests

# 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 test

Writing New Tests

Test files are located in src/test/java/. To add new tests:

  1. Create a test class in the appropriate package under src/test/java/
  2. Use JUnit 5 annotations (@Test, @BeforeEach, @DisplayName)
  3. Follow the existing test patterns in StringStorageTest.java
  4. Run mvn test to verify your tests pass

Future Test Plans

Planned test coverage for:

  • Stream Operations (XADD, XRANGE, XREAD with blocking)
  • Replication (Master-replica sync, command propagation)
  • RDB Persistence (Loading, saving, expiry handling)

🔮 Future Enhancements

  • Enhanced REPLICAOF command: allow dynamic switching between master and replica roles
  • Full sync: enable replicas to receive and load real RDB files from master

🙏 Acknowledgements

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.

About

A Redis-compatible key-value store built from scratch in Java.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors