Skip to content

About

A Redis-like in-memory key-value server written in C++. This project was built to study: - TCP networking - Non-blocking sockets - Event-driven servers - Hash tables - AVL trees - Sorted sets - TTL expiration - Thread pools - Custom binary protocols

Resources

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Built My Own Redis Server

A Redis-like in-memory key-value server written in modern C++.

This project was built as a hands-on study of how database servers work internally, including TCP networking, non-blocking sockets, event-driven programming, hash tables, AVL trees, sorted sets, TTL expiration, thread pools, and custom binary protocols.

Educational project: This is not a drop-in replacement for Redis and does not implement the Redis RESP protocol. Use the included client program to communicate with the server.


Features

  • In-memory key-value storage
  • TCP client-server communication
  • Non-blocking sockets
  • Event-driven server loop using poll()
  • Custom binary request and response protocol
  • Hash-table-based key lookup
  • String values
  • Sorted sets with scores
  • AVL-tree-backed sorted-set operations
  • Key expiration with millisecond precision
  • TTL inspection
  • Idle connection timeout handling
  • Thread pool for cleaning up large data structures
  • Native C++ client
  • Optional browser-based command console
  • Automated command tests

Project Structure

The repository contains several progressive versions of the server. The latest implementation is located in the 14 directory.

.
├── 03/
├── 04/
├── 06/
├── 07/
├── 08/
├── 09/
├── 10/
├── 11/
├── 12/
├── 13/
└── 14/
    ├── 14_server.cpp
    ├── 14_client.cpp
    ├── common.h
    ├── hashtable.cpp
    ├── hashtable.h
    ├── avl.cpp
    ├── avl.h
    ├── zset.cpp
    ├── zset.h
    ├── heap.cpp
    ├── heap.h
    ├── list.h
    ├── thread_pool.cpp
    ├── thread_pool.h
    ├── test_cmds.py
    ├── web_api.py
    ├── Makefile
    └── README.md

Each numbered directory represents a stage in the development of the project, with the latest and most complete version currently in 14.


Requirements

Linux

Install the following tools:

  • GNU C++ compiler
  • GNU Make
  • Python 3
  • POSIX-compatible environment

On Ubuntu or Debian:

sudo apt update
sudo apt install g++ make python3

Windows

The server uses POSIX APIs such as:

  • unistd.h
  • poll()
  • POSIX sockets
  • pthreads

The recommended way to run it on Windows is through WSL:

wsl --install -d Ubuntu

After installing Ubuntu, open a WSL terminal and install the required packages:

sudo apt update
sudo apt install g++ make python3

Build

Clone the repository and move into the latest version:

git clone https://github.com/CoderNasim2023/Built-myownRedis_Server.git
cd Built-myownRedis_Server/14

Build the server and client:

make

This produces:

redis_server
redis_client

To remove compiled binaries:

make clean

Run the Server

Start the server:

./redis_server

The server listens on:

127.0.0.1:1234

Keep the server running in one terminal.


Use the Client

Open a second terminal, move into the 14 directory, and run commands using the included client.

Store and retrieve a value

./redis_client set name redis
./redis_client get name

Expected output:

(nil)
(str) redis

Delete a key

./redis_client del name

List keys

./redis_client keys

Set a key expiration

Set a key to expire after five seconds:

./redis_client set temporary hello
./redis_client pexpire temporary 5000

Check the remaining time-to-live:

./redis_client pttl temporary

A return value of:

-1

means the key exists without an expiration time.

A return value of:

-2

means the key does not exist.

Sorted sets

Add members to a sorted set:

./redis_client zadd ranking 10 alice
./redis_client zadd ranking 20 bob
./redis_client zadd ranking 15 charlie

Read a member's score:

./redis_client zscore ranking alice

Remove a member:

./redis_client zrem ranking alice

Query members ordered by score:

./redis_client zquery ranking 0 "" 0 10

Supported Commands

Command Description
set key value Store a string value
get key Retrieve a string value
del key Delete a key
keys Return all stored keys
pexpire key milliseconds Set or update a key expiration
pttl key Return the remaining TTL
zadd zset score member Add or update a sorted-set member
zrem zset member Remove a sorted-set member
zscore zset member Return a member's score
zquery zset score member offset limit Query sorted-set members by score

Run Tests

The project includes an automated test script that starts the server, executes commands, checks the responses, and shuts the server down.

From the 14 directory:

make test

The test suite currently verifies:

  • Setting and retrieving string values
  • Adding sorted-set members
  • Reading sorted-set scores
  • Querying sorted sets
  • Deleting keys
  • Confirming deleted keys no longer exist

A successful run prints:

All version 14 command tests passed.

Browser Dashboard

The project also includes a small browser-based command console.

First, start the Redis-like server:

./redis_server

Then, in another terminal, start the web interface:

make web

Open the following address in your browser:

http://localhost:3000

The request flow is:

Browser
   │
   ▼
HTTP bridge on port 3000
   │
   ▼
Redis-like server on port 1234

Example commands that can be entered in the browser console:

set name redis
get name
keys
zadd ranking 10 alice
zscore ranking alice

How It Works

Network Layer

The server creates a TCP listening socket on port 1234.

Client connections are configured as non-blocking sockets. The server uses poll() to monitor:

  • New incoming connections
  • Readable client sockets
  • Writable client sockets
  • Socket errors

This allows the server to handle multiple clients without blocking on a single connection.

Request Processing

Requests use a custom binary format:

message length
argument count
argument length
argument data
argument length
argument data
...

The server parses the request, executes the command, and serializes the response using typed values such as:

  • Nil
  • Error
  • String
  • Integer
  • Double
  • Array

Key-Value Storage

Top-level keys are stored in a custom hash table.

String values are stored directly in the associated entry. Sorted sets use a separate data structure that supports lookup by member and ordered queries by score.

TTL Expiration

Expiring keys are stored in a min-heap ordered by expiration time.

During the event loop, the server checks the next timer and removes expired keys when their TTL has elapsed.

Sorted Sets

Sorted sets support:

  • Member lookup
  • Score lookup
  • Insertion and updates
  • Removal
  • Ordered range-style queries

The implementation combines hash-table lookup with an AVL-tree-based ordered structure.

Thread Pool

A small thread pool is used to clean up large data structures without blocking the main event loop for too long.


Custom Protocol Notice

This project does not implement the Redis Serialization Protocol, also known as RESP.

Therefore, standard Redis tools such as the following will not work:

redis-cli

Use the included client instead:

./redis_client get name

The browser dashboard also communicates using the project's custom protocol through the Python HTTP bridge.


Learning Goals

This project was created to explore the implementation details behind systems such as Redis.

The main learning areas include:

  • TCP socket programming
  • Non-blocking I/O
  • Event-driven architecture
  • Request pipelining
  • Binary serialization
  • Hash-table implementation
  • AVL trees
  • Sorted sets
  • Priority heaps
  • TTL management
  • Connection timeouts
  • Thread pools
  • Client-server protocol design
  • Automated integration testing

Limitations

This project is intended for learning and experimentation.

It currently does not provide the full feature set of Redis, including:

  • Redis RESP compatibility
  • Persistence to disk
  • Authentication
  • Replication
  • Transactions
  • Pub/Sub
  • Cluster support
  • Production-level configuration
  • Comprehensive concurrency guarantees
  • Full Redis command compatibility

Do not use this project as a production database.


Future Improvements

Potential future improvements include:

  • RESP protocol support
  • Persistent snapshots
  • Append-only file persistence
  • More Redis data types
  • Better command parsing
  • More extensive integration tests
  • Improved concurrency control
  • Configuration files
  • Graceful shutdown support
  • Performance benchmarks
  • Docker support
  • CI/CD automation

License

No license has currently been specified for this repository.

If you plan to allow others to use, modify, or distribute the project, consider adding an open-source license such as MIT or Apache-2.0.


Author

Created by CoderNasim2023.

If you found this project useful, consider starring the repository.

About

A Redis-like in-memory key-value server written in C++. This project was built to study: - TCP networking - Non-blocking sockets - Event-driven servers - Hash tables - AVL trees - Sorted sets - TTL expiration - Thread pools - Custom binary protocols

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages