|
|
@@ -0,0 +1,120 @@
|
|
|
+# 🍕 PizzaKV
|
|
|
+
|
|
|
+An in-memory key-value store written in Zig with Redis protocol compatibility and persistent storage.
|
|
|
+
|
|
|
+## Overview
|
|
|
+
|
|
|
+PizzaKV is a concurrent key-value database that implements a subset of the Redis RESP (REdis Serialization Protocol), allowing it to work with Redis clients for supported commands. It also supports a simpler custom protocol (Pizzaria Protocol) using `\r` delimiters. Built from scratch in Zig.
|
|
|
+
|
|
|
+## Features
|
|
|
+
|
|
|
+- **Dual Protocol Support**:
|
|
|
+ - RESP (Redis Serialization Protocol) - subset implementation compatible with Redis clients
|
|
|
+ - Pizzaria Protocol - simple `\r`-delimited custom protocol
|
|
|
+- **Persistent Storage**: Append-only file (AOF) persistence with buffered writes
|
|
|
+- **Prefix Search**: Built-in radix tree index for efficient prefix-based queries
|
|
|
+- **Thread-Safe**: Concurrent operations using sharded hash tables and RwLocks
|
|
|
+- **Zero Dependencies**: Pure Zig implementation with no external dependencies
|
|
|
+
|
|
|
+## Supported Commands
|
|
|
+
|
|
|
+### RESP Protocol (Redis-compatible)
|
|
|
+- `SET key value` - Store a key-value pair
|
|
|
+- `GET key` - Retrieve a value by key
|
|
|
+- `DEL key` - Delete a key
|
|
|
+
|
|
|
+### Pizzaria Protocol (`\r`-delimited)
|
|
|
+- `write key|value` - Write a key-value pair (key and value separated by `|`)
|
|
|
+- `read key` - Read a value by key
|
|
|
+- `delete key` - Delete a key
|
|
|
+- `keys` - Get all keys (using radix tree)
|
|
|
+- `reads prefix` - Get all values for keys matching a prefix
|
|
|
+- `status` - Server status check
|
|
|
+
|
|
|
+## Architecture
|
|
|
+
|
|
|
+### Core Components
|
|
|
+
|
|
|
+- **Sharded Hash Table**: 64 shards with 1,048,576 total buckets for parallel access
|
|
|
+- **Radix Tree Index**: Fast prefix search and key enumeration
|
|
|
+- **Persistence Layer**: 8MB write buffer with automatic flushing
|
|
|
+- **TCP Server**: Async I/O with connection pooling
|
|
|
+
|
|
|
+### Concurrency Model
|
|
|
+
|
|
|
+- **Per-shard RwLocks**: Allow concurrent reads within each shard
|
|
|
+- **Global tree mutex**: Protects radix tree modifications
|
|
|
+- **Atomic connection tracking**: For graceful shutdown
|
|
|
+
|
|
|
+## Building
|
|
|
+
|
|
|
+```bash
|
|
|
+# Build optimized binary
|
|
|
+make build
|
|
|
+
|
|
|
+# Clean build artifacts
|
|
|
+make clean
|
|
|
+```
|
|
|
+
|
|
|
+## Running
|
|
|
+
|
|
|
+```bash
|
|
|
+# Start server in Redis mode (RESP protocol, port 8085)
|
|
|
+./pizzakv -redis
|
|
|
+
|
|
|
+# Start server in Pizzaria mode (\r-delimited protocol, port 8085)
|
|
|
+./pizzakv
|
|
|
+
|
|
|
+# The server will create a .db file for persistence
|
|
|
+```
|
|
|
+
|
|
|
+## Technical Details
|
|
|
+
|
|
|
+### Memory Management
|
|
|
+
|
|
|
+- Arena allocators for hash table entries (per-shard)
|
|
|
+- Arena allocator for radix tree nodes
|
|
|
+- C allocator for temporary operations
|
|
|
+
|
|
|
+### Hash Function
|
|
|
+
|
|
|
+- FNV-1a hash with bit mixing for uniform distribution
|
|
|
+- Minimizes collisions across 1M buckets
|
|
|
+
|
|
|
+### Persistence Format
|
|
|
+
|
|
|
+Simple append-only format:
|
|
|
+```
|
|
|
+OPCODE|key|value\r
|
|
|
+```
|
|
|
+
|
|
|
+- `W|key|value\r` - Write operation
|
|
|
+- `D|key|\r` - Delete operation
|
|
|
+
|
|
|
+### Thread Safety
|
|
|
+
|
|
|
+- Shard-level RwLocks for concurrent hash table access
|
|
|
+- Global mutex for radix tree operations
|
|
|
+- Atomic counters for connection tracking
|
|
|
+
|
|
|
+## Project Structure
|
|
|
+
|
|
|
+```
|
|
|
+pizzakv/
|
|
|
+├── main.zig # Server, connection handling
|
|
|
+├── storage.zig # Sharded hash table
|
|
|
+├── index.zig # Radix tree for prefix search
|
|
|
+├── persistence.zig # AOF persistence layer
|
|
|
+├── hashing.zig # Hash function
|
|
|
+├── redis.zig # RESP protocol parser
|
|
|
+├── command.zig # Command execution
|
|
|
+├── socket.zig # TCP socket operations
|
|
|
+└── benchmark_*.sh # Benchmark scripts
|
|
|
+```
|
|
|
+
|
|
|
+## Notes
|
|
|
+
|
|
|
+- This implements a subset of RESP, not the full Redis protocol
|
|
|
+- RESP commands are limited to SET, GET, and DEL
|
|
|
+- The Pizzaria protocol provides additional commands (prefix search)
|
|
|
+- Built with Zig 0.15.1 using `-O ReleaseFast` optimization
|