This project is an implementation of the RESP (REdis Serialization Protocol) in Go, based on the tutorial from Build Redis from Scratch. It extends the basic functionality with additional features like TTL (Time To Live) support and key eviction strategies.
RESP is a simple, binary-safe protocol used by Redis for client-server communication. This implementation provides a structure for reading and writing RESP-encoded data, handling basic Redis commands, and managing data expiration.
- Parsing of RESP data types: Simple Strings, Errors, Integers, Bulk Strings, Arrays
- RESP writer functionality for encoding responses
- Error handling for invalid inputs
- CLI flags for server configuration
- TTL support for key expiration
- Active and passive eviction strategies
- Basic Redis commands:
- GET: Retrieve the value of a key
- SET: Set the value of a key
- SETEX: Set the value and expiration of a key
- DEL: Delete one or more keys
- PING: Test if the server is responsive
- EXPIRE: Set the expiration time of a key
Crapis implements two eviction strategies for handling key expiration:
-
Passive Eviction: When a GET operation is performed on a key, the system checks if the key has expired. If it has, the key is deleted, and a nil value is returned.
-
Active Eviction: A background goroutine runs periodically to check for and remove expired keys. This process helps to free up memory proactively, rather than waiting for keys to be accessed.
-
TTL Registry: The system maintains a separate map (
ttlKeys
) to keep track of keys with TTL. This optimization allows for efficient checking of keys that may have expired. -
Expiration Check:
- Passive: Performed during GET operations.
- Active: A goroutine runs every 250 milliseconds to check for expired keys.
-
Deletion Process:
- The active eviction process uses a two-pass approach to minimize lock contention:
- It first scans for expired keys using a read lock.
- Then it deletes the expired keys, acquiring a write lock only for the actual deletion.
- The active eviction process uses a two-pass approach to minimize lock contention:
- Go 1.16 or higher
- Clone the repository:
git clone https://github.com/marianozunino/crapis.git
- Navigate to the project directory:
cd crapis
To interact with the server, you can use redis-cli
:
redis-cli -p 6379
Then you can use the implemented commands:
> SET mykey "Hello"
OK
> GET mykey
"Hello"
> SETEX tempkey 10 "This will expire"
OK
> PING
PONG
> DEL mykey tempkey
(integer) 2
To run the server, use the go run .
command. You can configure the server using the following CLI flags:
Usage:
crapis [flags]
Flags:
-f, --aof string Path to AOF file (default "database.aof")
-a, --aof-enabled Enable AOF
-b, --bind string Bind address (default "0.0.0.0")
-d, --debug Enable debug mode
-i, --eviction-interval-ms int Eviction interval in milliseconds (default 250)
-t, --eviction-timeout-ms int Eviction timeout in milliseconds, must be at at most half of eviction-interval-ms (default 10)
-h, --help help for crapis
-e, --passive-eviction Enable passive eviction (default true)
-p, --port string Port to listen on (default "6379")
For example, to run the server on a different port with debug mode enabled:
go run . -p 7000 -d
This will start the server on port 7000 with debug logging enabled.
To run the tests for this project, use the following command:
go test ./...
This project is licensed under the MIT License - see the LICENSE file for details.
- Build Redis from Scratch for the tutorial and inspiration.