Skip to content

GinaShome/CacheForge

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Mini Redis in C++

A small Redis-like in-memory key-value store built with C++17 and Linux/POSIX sockets. It uses a simple line-oriented text protocol, handles concurrent TCP clients with one thread per connection, supports TTL expiration, and rebuilds state from an append-only log on startup.

Features

  • TCP server with configurable port
  • Concurrent clients using one thread per client
  • Redis-style text commands: SET, GET, DEL, EXPIRE, TTL, PING, QUIT
  • Thread-safe in-memory hash table storage
  • Lazy TTL expiration for keys
  • Append-only persistence for write commands
  • Startup replay from the append-only log
  • Small multi-client benchmark client

Build

Requires Linux, make, and a C++17 compiler.

make

This creates:

  • mini_redis - the server
  • kv_bench - the benchmark client

Run

./mini_redis 6379 mini_redis.aof

Arguments:

  • 6379 is the TCP port
  • mini_redis.aof is the append-only persistence log

If no arguments are provided, the server uses port 6379 and mini_redis.aof.

Protocol

Clients send one command per line. The server returns one text response per command.

Supported commands:

SET key value
GET key
DEL key
EXPIRE key seconds
TTL key
PING
QUIT

Response behavior:

  • SET returns OK
  • GET returns the value or nil
  • DEL returns 1 if a key was removed, otherwise 0
  • EXPIRE returns 1 if a TTL was set, otherwise 0
  • TTL returns remaining seconds, -1 for no TTL, or -2 for missing/expired keys
  • PING returns PONG
  • QUIT returns OK and closes the connection
  • malformed commands return ERR ...

Manual Test With Netcat

Start the server:

./mini_redis 6379 mini_redis.aof

In another terminal:

nc localhost 6379

Example session:

OK mini-redis ready
SET name ABC
OK
GET name
ABC
DEL name
1
GET name
nil
SET temp hello
OK
EXPIRE temp 30
1
TTL temp
27
PING
PONG
QUIT
OK

Persistence Test

./mini_redis 6379 mini_redis.aof

Then from nc:

SET project redis-lite
OK
QUIT
OK

Stop and restart the server with the same log file:

./mini_redis 6379 mini_redis.aof

Check the value:

GET project
redis-lite

The append-only log stores write commands such as SET, DEL, and EXPIRE. On startup, the server replays the log before accepting clients.

Benchmark

Start the server first:

./mini_redis 6379 mini_redis.aof

Run the benchmark:

./kv_bench 6379 8 1000

Arguments:

  • 6379 - server port
  • 8 - number of concurrent clients
  • 1000 - SET/GET operation pairs per client

Example output:

clients=8 operations_per_client=1000 total_commands=16000 elapsed_seconds=0.72 throughput_cmds_per_sec=22222 failures=0

Architecture

flowchart LR
    client1["Client: nc / app"] --> listener["TCP listener<br/>src/server.cpp"]
    client2["Benchmark clients<br/>tools/benchmark.cpp"] --> listener

    listener --> accept["accept() loop"]
    accept --> thread["Client handler thread<br/>one per connection"]

    thread --> parser["Command parser<br/>src/command_parser.cpp"]
    parser --> router["Command execution<br/>SET / GET / DEL / EXPIRE / TTL / PING / QUIT"]

    router --> store["Thread-safe KV store<br/>src/kv_store.cpp<br/>unordered_map + mutex"]
    store --> ttl["Lazy TTL expiration<br/>expires_at per key"]

    router --> writes["Write command guard<br/>server-level mutex"]
    writes --> aof["Append-only log<br/>mini_redis.aof"]
    writes --> store

    startup["Startup<br/>src/main.cpp"] --> replay["Replay append-only log<br/>src/persistence.cpp"]
    replay --> store
Loading
  • src/main.cpp parses startup arguments, replays persistence, and starts the server.
  • src/server.cpp owns the TCP listener, accepts clients, spawns client threads, reads line-based commands, and writes responses.
  • src/command_parser.cpp converts text input into typed commands and validates arity.
  • src/kv_store.cpp stores keys in an std::unordered_map protected by a mutex and lazily removes expired keys.
  • src/persistence.cpp appends write commands to disk and replays them on startup.
  • tools/benchmark.cpp opens multiple client connections and measures SET/GET throughput.

Writes are protected by a server-level mutex so append-only log order matches in-memory mutation order. The key-value store has its own mutex to protect shared data for both reads and writes.

About

A small Redis-like in-memory key-value store built with C++17 and Linux/POSIX sockets. It uses a simple line-oriented text protocol, handles concurrent TCP clients with one thread per connection, supports TTL expiration, and rebuilds state from an append-only log on startup.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors