Skip to content

University project to create a Redis clone (in-memory key-value database) using Tokio asynchronous runtime.

License

Notifications You must be signed in to change notification settings

matejfric/redis-clone

Repository files navigation

Simple Redis Clone

GitHub codecov made-with-rust GitHub license

1. Usage

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

2. Notes from Redis Protocol Specification

Sending commands to a Redis server:

  1. A client sends the Redis server an array consisting of only bulk strings.
  2. 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.

3. Progress

  • Implement RESP parser and serializer for selected types.

    • Simple strings
    • Errors
    • Integers
    • Bulk strings
    • Arrays
    • Null
  • Implement selected Redis commands.

3.1. Optional

4. Architecture Overview

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
Loading
  • connection.rs wraps tokio::net::TcpStream and provides easy to use API for RESP. It works with frames defined in frame.rs (a frame is a Redis datatype).
  • server.rs and client.rs both use connection.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.

5. Contributing

Please setup pre-commit hooks with the provided script:

sh setup-git-hooks.sh 

5.1. Testing

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].

6. Sources

About

University project to create a Redis clone (in-memory key-value database) using Tokio asynchronous runtime.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published