The slow and steady cache wins the race.
SnakeCache is a Redis-like in-memory cache server implemented in pure Python, designed for learning and fun. While it may not be as fast as Redis, it's a great way to understand how in-memory caches work and perfect for educational purposes or small projects.
- Pure Python Implementation: Built from scratch using Python's asyncio
- Redis-Compatible Protocol: Implements RESP (Redis Serialization Protocol)
- Core Data Structures:
- Strings with expiration
- Lists with basic operations
- Key Space Management:
- Key expiration (TTL)
- Key existence checks
- Atomic operations
- Connection Management:
- Connection pooling
- Socket optimization
- Command timeouts
# Clone the repository
git clone https://github.com/devbijay/SnakeCache.git
cd SnakeCache
# Install dependencies
pip install -r requirements.txt
# Start the server
python -m snakecache.server# Install uv if you haven't already
pip install uv
# Clone the repository
git clone https://github.com/devbijay/SnakeCache.git
cd SnakeCache
# Install dependencies using uv
uv sync
# Start the server
uv run server.py# Build the Docker image
docker build -t snakecache .
# Run the container
docker run -d \
--name snakecache \
-p 6379:6379 \
-e SNAKE_CACHE_PORT=6379 \
-e SNAKE_CACHE_MAX_CLIENTS=10000 \
snakecache
# Check logs
docker logs -f snakecache# docker-compose.yml
version: '3.8'
services:
snakecache:
build: .
ports:
- "6379:6379"
environment:
- SNAKE_CACHE_PORT=6379
- SNAKE_CACHE_MAX_CLIENTS=10000
restart: unless-stoppedRun with:
docker-compose up -dConnect using any Redis client:
import redis
r = redis.Redis(host='localhost', port=6379)
r.set('hello', 'world')
print(r.get('hello')) # b'world'SET key value- Set key to hold string valueSETEX key seconds value- Set key with expirySETNX key value- Set key only if not existsGET key- Get value of key
DEL key [key ...]- Delete one or more keysEXISTS key [key ...]- Check if keys existEXPIRE key seconds- Set key timeoutTTL key- Get remaining time to live
LPUSH/RPUSH key value [value ...]- Push to listLPOP/RPOP key- Pop from listLRANGE key start stop- Get range of elementsLLEN key- Get list length
PING [message]- Test connectionINFO- Server information
Environment variables:
SNAKE_CACHE_PORT=6379 # Server port
SNAKE_CACHE_MAX_CLIENTS=10000 # Maximum clients
SNAKE_CACHE_BACKLOG=2048 # Connection backlogSnakeCache is built with a modular architecture:
Key components:
- Server: Handles connections and protocol parsing
- Command Handler: Processes and routes commands
- Data Store: Manages data structures and persistence
- Expiry Manager: Handles key expiration
-
Memory Management
- LRU-based memory management
- Automatic key expiration
- Per-key locking for concurrent access
-
Protocol Handling
- Efficient RESP protocol implementation
- Pre-compiled responses for common operations
- Optimized buffer management
-
Connection Handling
- Asynchronous I/O with asyncio
- Connection pooling
- Command timeouts
- Error handling
Contributions are welcome! This is a fun project meant for learning and experimentation. Feel free to:
- Fork the repository
- Create a feature branch
- Submit a pull request
Areas for improvement:
- Add more data structures (Sets, Hashes, etc.)
- Implement persistence
- Add clustering support
- Improve performance
- Add more tests
MIT License - feel free to use this for learning, fun, or even as a starting point for your own cache implementation!
SnakeCache is a learning project and not intended for production use. For production environments, please use Redis or other battle-tested solutions.
Made with π and β€οΈ