A Python implementation of a Redis-like in-memory database server, built as part of the CodeCrafters Redis Challenge. This project implements a subset of Redis commands and the RESP (Redis Serialization Protocol) for client-server communication.
- PING - Health check command
- ECHO - Echo back the provided message
- SET - Set a key-value pair with optional expiration
- GET - Retrieve a value by key
- CONFIG GET - Get configuration parameters
- KEYS - List all keys matching a pattern
- LPUSH - Push elements to the left of a list
- RPUSH - Push elements to the right of a list
- LPOP - Remove and return the leftmost element
- RPOP - Remove and return the rightmost element
- LRANGE - Get a range of elements from a list
- LLEN - Get the length of a list
- TYPE - Get the data type of a key
- RESP Protocol - Full implementation of Redis Serialization Protocol
- RDB Support - Load initial data from Redis dump files
- Expiration - Support for key expiration with PX (milliseconds)
- Asynchronous I/O - Built with Python's asyncio for high performance
- Graceful Shutdown - Proper signal handling for clean server shutdown
├── app/
│ ├── __init__.py
│ ├── main.py # Server entry point and connection handling
│ ├── redis_command.py # Command implementations and handler
│ ├── redis_parser.py # RESP protocol parser and serializer
│ └── rdb_reader.py # RDB file format reader
├── codecrafters.yml # CodeCrafters configuration
├── Pipfile # Python dependencies
├── your_program.sh # Local execution script
├── example.bash # Example client commands
└── README.md # This file
- Python 3.8+
- pipenv (for dependency management)
-
Clone the repository:
git clone <repository-url> cd codecrafters-redis-python
-
Install dependencies:
pipenv install
# Run the server locally
./your_program.sh
# Or directly with pipenv
pipenv run python3 -m app.main# Run on a different port
pipenv run python3 -m app.main --port 6380
# Load data from RDB file
pipenv run python3 -m app.main --dir /path/to/data --dbfilename dump.rdbtelnet localhost 6379redis-cli -p 6379# Health check
*1\r\n$4\r\nPING\r\n
# Echo a message
*2\r\n$4\r\nECHO\r\n$11\r\nHello World\r\n
# Set a key-value pair
*3\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$10\r\nHello Redis\r\n
# Get a value
*2\r\n$3\r\nGET\r\n$5\r\nmykey\r\n
# Set with expiration (5 seconds)
*5\r\n$3\r\nSET\r\n$5\r\nmykey\r\n$10\r\nHello Redis\r\n$2\r\nPX\r\n$4\r\n5000\r\n# Push to list
*3\r\n$5\r\nLPUSH\r\n$4\r\nmylist\r\n$5\r\nworld\r\n
*3\r\n$5\r\nLPUSH\r\n$4\r\nmylist\r\n$5\r\nhello\r\n
# Get list range
*4\r\n$6\r\nLRANGE\r\n$4\r\nmylist\r\n$1\r\n0\r\n$1\r\n-1\r\n
# Pop from list
*2\r\n$4\r\nLPOP\r\n$4\r\nmylist\r\n-
RESP Parser/Serializer (
redis_parser.py)- Parses incoming RESP protocol messages
- Serializes responses back to RESP format
- Handles different RESP data types (Simple Strings, Errors, Integers, Bulk Strings, Arrays)
-
Command Handler (
redis_command.py)- Implements all Redis commands as separate classes
- Uses abstract base class pattern for extensibility
- Handles command validation and execution
-
RDB Reader (
rdb_reader.py)- Reads Redis dump files for initial data loading
- Supports basic RDB format parsing
-
Main Server (
main.py)- Asynchronous TCP server using asyncio
- Handles multiple concurrent connections
- Implements graceful shutdown with signal handling
The server can be configured via command-line arguments:
--port <port>: Specify the port to listen on (default: 6379)--dir <directory>: Directory containing RDB files--dbfilename <filename>: Name of the RDB file to load
This is a learning implementation and has some limitations compared to the full Redis:
- Limited command set (no hashes, sets, sorted sets)
- No persistence beyond RDB loading
- No replication or clustering
- No authentication or security features
- Limited configuration options
This project is part of the CodeCrafters Redis Challenge. For the full challenge experience, visit codecrafters.io.
This project is for educational purposes as part of the CodeCrafters challenge.