A lightweight, educational implementation of Redis server in Java, featuring in-memory key-value storage with support for basic Redis commands and the Redis Serialization Protocol (RESP).
- Overview
- Features
- Architecture
- Getting Started
- Supported Commands
- Implementation Details
- Project Structure
- Contributing
This project is an educational Redis clone that implements core Redis functionality using Java. It demonstrates key concepts in distributed systems, network programming, and concurrent data structures. The server listens on the standard Redis port (6379) and communicates using the Redis Serialization Protocol (RESP), making it compatible with standard Redis clients.
Key Highlights:
- β Multi-threaded TCP server supporting concurrent client connections
- β In-memory key-value store with thread-safe operations
- β RESP (Redis Serialization Protocol) implementation
- β TTL (Time To Live) support for automatic key expiration
- β Clean architecture with separation of concerns
- Multi-Client Support: Handles multiple concurrent client connections using a thread-per-client model
- Thread-Safe Storage: Uses
ConcurrentHashMapfor safe concurrent access to stored data - TTL Support: Keys can be set with expiration times using the
PX(milliseconds) option - RESP Protocol: Full support for Redis Serialization Protocol encoding/decoding
- Configuration Management: Command-line argument parsing for server configuration
- Extensible Handler Pattern: Easy to add new Redis commands through the handler pattern
- Singleton Pattern: Used for
StorageandServerConfigto ensure single instances across the application - Strategy Pattern: Command handlers implement different strategies for handling Redis commands
- Template Method Pattern:
BaseHandlerprovides common structure for all handlers - Thread-Per-Client Model: Each client connection runs in its own thread
βββββββββββββββββββ
β Main.java β β Entry point, creates ServerSocket on port 6379
ββββββββββ¬βββββββββ
β spawns
βΌ
βββββββββββββββββββ
β ClientHandler β β Routes commands to appropriate handlers
ββββββββββ¬βββββββββ
β uses
βΌ
βββββββββββββββββββββββββββββββββββββββββββββββββββ
β Handler Classes β
β β’ SetHandler β’ GetHandler β
β β’ PingHandler β’ EchoHandler β
β β’ ConfigHandler β
βββββββββββββββββββ¬ββββββββββββββββββββββββββββββββ
β accesses
βΌ
βββββββββββββββββββ
β Storage β β Thread-safe ConcurrentHashMap
β (Singleton) β
βββββββββββββββββββ
- Java 8 or higher
- A Redis client (redis-cli, or any Redis-compatible client)
cd java
javac Main.java# Basic usage
java Main
# With configuration options
java Main --dir /path/to/data --dbfilename dump.rdbThe server will start listening on tcp://localhost:6379
redis-cli -p 6379| Command | Syntax | Description | Example |
|---|---|---|---|
| PING | PING |
Returns PONG | PING β PONG |
| ECHO | ECHO message |
Returns the message | ECHO "Hello" β "Hello" |
| SET | SET key value [PX milliseconds] |
Set a key-value pair with optional TTL | SET mykey "Hello" β OK |
| GET | GET key |
Get the value of a key | GET mykey β "Hello" |
| CONFIG | CONFIG GET parameter |
Get configuration parameter | CONFIG GET dir |
- Basic SET:
SET key value- Stores a key-value pair - SET with Expiry:
SET key value PX milliseconds- Stores with TTL in milliseconds
Example:
127.0.0.1:6379> SET session:123 "user_data" PX 10000
OK
127.0.0.1:6379> GET session:123
"user_data"
# After 10 seconds
127.0.0.1:6379> GET session:123
(nil)The project uses ConcurrentHashMap from java.util.concurrent to ensure thread-safe operations on the key-value store. This allows multiple client threads to read and write simultaneously without data corruption.
TTL (Time To Live) is implemented using Java's Timer and TimerTask:
- When a key is set with a timeout, a timer task is scheduled
- The task automatically removes the key after the specified timeout
- Supports millisecond precision using the
PXoption
The Encoder class implements RESP encoding for:
- Simple Strings:
+OK\r\n - Bulk Strings:
$5\r\nHello\r\n - Arrays:
*2\r\n$3\r\nGET\r\n$5\r\nmykey\r\n - Null:
$-1\r\n
- Port: 6379 (standard Redis port)
- Socket Timeout: 10 seconds
- Reuse Address: Enabled for quick restarts
- I/O: Buffered readers/writers for efficient communication
Redis_Clone/
βββ README.md
βββ java/
βββ Main.java # Server entry point
βββ config/
β βββ ServerConfig.java # Configuration singleton
βββ storage/
β βββ Storage.java # Thread-safe in-memory store
βββ client/
βββ ClientHandler.java # Client connection handler
βββ Encoder.java # RESP protocol encoder
βββ ResponseConstants.java # Response string constants
βββ handlers/
βββ BaseHandler.java # Base handler class
βββ IHandler.java # Handler interface
βββ PingHandler.java # PING command handler
βββ EchoHandler.java # ECHO command handler
βββ SetHandler.java # SET command handler
βββ GetHandler.java # GET command handler
βββ IOHelper.java # I/O utility methods
βββ config/
βββ ConfigHandler.java # CONFIG command handler
Contributions are welcome! Here are some ways you can contribute:
- Add New Commands: Implement additional Redis commands (DEL, EXISTS, INCR, etc.)
- Improve Performance: Optimize data structures and algorithms
- Add Persistence: Implement RDB or AOF persistence
- Enhanced Testing: Add unit and integration tests
- Documentation: Improve code comments and documentation
- Create a new handler class in
client/handlers/extendingBaseHandler - Implement the
handle()method - Add command routing in
ClientHandler.java
Example:
public class DelHandler extends BaseHandler {
public DelHandler(Socket socket, BufferedReader in, BufferedWriter out) {
super(socket, in, out);
}
@Override
public void handle() throws IOException {
// Implementation
}
}Note: This is an educational project demonstrating Redis concepts. It is not intended for production use. For production applications, use the official Redis server.