- 1. Usage
- 2. Notes from Redis Protocol Specification
- 3. Progress
- 4. Architecture Overview
- 5. Contributing
- 6. Sources
Start the server with cargo run
:
RUST_LOG=info cargo run --bin server
Once started, the server can be used manually, for example with nc
:
echo -e '*3\r\n$3\r\nSET\r\n$6\r\nanswer\r\n$2\r\n42\r\n' | nc 127.0.0.1 6379
echo -e '*2\r\n$3\r\nGET\r\n$6\r\nanswer\r\n' | nc 127.0.0.1 6379
or with redis-cli
:
redis-cli -h 127.0.0.1 -p 6379
set answer 42
get answer
Sending commands to a Redis server:
- A client sends the Redis server an array consisting of only bulk strings.
- A Redis server replies to clients, sending any valid RESP data type as a reply.
Example:
C: *2\r\n
C: $4\r\n
C: LLEN\r\n
C: $6\r\n
C: mylist\r\n
S: :42\r\n
(The actual interaction is the client sending *2\r\n$4\r\nLLEN\r\n$6\r\nmylist\r\n
as a whole.)
Simple strings never contain carriage return (\r) or line feed (\n) characters. Bulk strings can contain any binary data and may also be referred to as binary or blob.
The difference between simple strings and errors in RESP is that clients should treat errors as exceptions, whereas the string encoded in the error type is the error message itself.
-
Implement RESP parser and serializer for selected types.
- Simple strings
- Errors
- Integers
- Bulk strings
- Arrays
- Null
-
Implement selected Redis commands.
- Limit maximum number of active clients.
- Redis pipelining
- Tokio codec
- Sharded DB
- LOLWUT (kind of)
The implementation uses Tokio for asynchronous I/O.
graph TD
style Connection fill:#aaa,stroke:#333,stroke-width:2,color:#000
style Frame fill:#aaa,stroke:#333,stroke-width:2,color:#000
style Cmd fill:#aaa,stroke:#333,stroke-width:2,color:#000
style Server fill:#aaa,stroke:#333,stroke-width:2,color:#000
style Client fill:#aaa,stroke:#333,stroke-width:2,color:#000
style Database fill:#aaa,stroke:#333,stroke-width:2,color:#000
subgraph "Main Modules"
Connection["**connection.rs**<br>Wraps TcpStream"]
Frame["**frame.rs**<br>Redis datatypes (RESP)"]
Cmd["**cmd.rs**<br>Parses Redis commands"]
Server["**server.rs**<br>Redis server"]
Client["**client.rs**<br>Redis client"]
Database["**db.rs**<br>Database"]
end
Connection -- "Works with frames" --> Frame
Server -- "Uses" --> Connection
Client -- "Uses" --> Connection
Cmd -- "Parses frames" --> Frame
Server -- "Uses" --> Cmd
Client -- "Uses" --> Cmd
Server -- "Accesses database" --> Database
connection.rs
wrapstokio::net::TcpStream
and provides easy to use API for RESP. It works with frames defined inframe.rs
(a frame is a Redis datatype).server.rs
andclient.rs
both useconnection.rs
.cmd.rs
contains parsing of Redis commands, both server and client use it (it operates on frames)- Server accesses database
db.rs
. - Database is a simple in-memory key-value store with a periodic expiration checking.
Please setup pre-commit hooks with the provided script:
sh setup-git-hooks.sh
Tests are run before each push to the repository with .githooks/pre-push
. To run tests manually:
- Run tests with
cargo test
. - Run tests on a single thread with
cargo test -- --test-threads=1
. - Run a single test with
cargo test -- --test <test_file> [<test_name>] [--nocapture] [--exact]
.