Skip to content

Ataba29/KV-Database

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

71 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

KV-Database logo

A lightweight, persistent key-value database built from scratch in C++

Redis-inspired Β· event-driven Β· cross-platform Β· containerized

C++ CMake Docker Platform Tests License: MIT


About

ByteForge is a Redis-inspired key-value store that supports basic CRUD operations over a TCP connection. It is designed around a phonebook use case where string keys map to string values.

This is a personal learning project. The goal is not to build a production database, but to understand how databases, servers, networking, and concurrency actually work under the hood.

The server runs cross-platform on both Windows and Linux using platform-specific networking abstractions.


Table of Contents


Features

Feature Description
🧩 Custom HashMap Hand-rolled hash table with separate chaining for collision resolution and dynamic growth, protected by a std::shared_mutex for concurrent read/write safety
⚑ Event-Driven TCP Server Readiness-based event loop supporting many concurrent connections without one thread per client β€” epoll on Linux, IOCP on Windows (adapted via zero-byte WSARecv), both behind a shared IEventLoop interface selected automatically at compile time
🧡 Thread Pool Fixed pool of 3 worker threads executing actual command work (GET/INSERT/DELETE), decoupled from connection count
πŸ“ Command Parser Parses INSERT, GET, and DELETE commands from raw TCP bytes
πŸ•’ Snapshot Scheduler Background thread that automatically triggers RDB snapshots on a fixed interval
πŸ’Ύ Hybrid Persistence AOF logs every write in real time; RDB snapshots dump the full database every 5 minutes; AOF resets after each snapshot
🚦 Rate Limiting Per-IP and global request throttling using the Token Bucket algorithm
πŸ›‘ Graceful Shutdown Type stop to cleanly flush data and join all threads
🐳 Docker Support Multi-stage containerized build targeting Linux
πŸ” Authentication In progress

Commands

Connect to the server using ncat or any TCP client:

ncat 127.0.0.1 6625
Command Description Example
INSERT key value Inserts or updates a key-value pair INSERT Ahmed 51020651
GET key Retrieves the value for a key GET Ahmed
DELETE key Removes a key-value pair DELETE Ahmed

Architecture

Client (ncat / custom client)
        β”‚
        β”‚ TCP
        β–Ό
 Cross-Platform TCP Server
 (Winsock2 / Linux sockets)
        β”‚
        β–Ό
 Event Loop (readiness-based)
 epoll (Linux) / IOCP (Windows)
 behind a shared IEventLoop interface
        β”‚  watches all client sockets;
        β”‚  reports which ones are ready
        β–Ό
        β”œβ”€β”€β–Ά Rate Limiter (Token Bucket)
        β”‚    per-IP + global request cap
        β”‚         β”‚
        β”‚         β–Ό
        β”‚    Command Parser
        β”‚         β”‚
        β”‚         β–Ό
        β”‚    Thread Pool (3 workers)
        β”‚    executes actual GET/INSERT/DELETE
        β”‚         β”‚
        β”‚         β–Ό
        β”‚    HashMap (in-memory store)
        β”‚    shared_mutex: readers run concurrently,
        β”‚    writers get exclusive access
        β”‚
        └──▢ Persistence Layer
                  β”œβ”€β”€ appendonly.log  (real-time AOF log)
                  └── snapshot.log    (periodic RDB snapshot)
                            β–²
                   SnapshotScheduler
                   (background thread, every 5 min)

Concurrency Model

Component Protection Strategy
Event Loop Single dedicated thread Watches all sockets for readiness; never blocks on I/O
Client jobs ThreadPool + std::condition_variable Only dispatched once a socket is actually readable
Connections busySockets guard (std::mutex) Prevents duplicate recv() jobs for the same socket
HashMap std::shared_mutex Multiple readers, exclusive writers
AOF stream std::mutex Single writer at a time
Snapshot SnapshotScheduler thread Sleeps on interval, wakes on shutdown
Rate limiter std::mutex per map + global Per-IP and global window isolated

Rate Limiting

ByteForge uses the Token Bucket algorithm for rate limiting β€” the same approach used by Stripe, GitHub, and AWS.

  • Each IP gets a bucket of tokens (default: 10)
  • Each request consumes one token
  • Tokens refill at a fixed rate (default: 5/sec)
  • A global cap limits total requests per second across all IPs (default: 1000)
  • Blocked requests are dropped immediately without consuming a worker thread

Getting Started

Prerequisites

  • C++17 compiler
  • CMake 3.15+
  • Docker (optional)
  • nmap/ncat for testing

For local builds:

  • Windows: MSVC / MinGW with Winsock2
  • Linux: GCC / Clang with POSIX sockets

Build Locally

cmake -S . -B build
cmake --build build

Run:

./build/Debug/KV_Database.exe   # Windows
./build/KV_Database             # Linux

The server starts on port 6625 by default. Type stop to shut it down cleanly.


Run With Docker

Build the image:

docker build -t byteforce:latest .

Run the container:

docker run -d -p 6625:6625 --name my-byteforce-db byteforce-db:latest

Connect using:

ncat 127.0.0.1 6625

Project Structure

kv-db/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ main.cpp
β”‚   β”œβ”€β”€ Server/
β”‚   β”‚   β”œβ”€β”€ Server.h
β”‚   β”‚   └── Server.cpp
β”‚   β”œβ”€β”€ Networking/
β”‚   β”‚   β”œβ”€β”€ NetworkTypes.h
β”‚   β”‚   β”œβ”€β”€ EventLoop.h
β”‚   β”‚   β”œβ”€β”€ EpollEventLoop.h / .cpp
β”‚   β”‚   β”œβ”€β”€ IocpEventLoop.h / .cpp
β”‚   β”‚   └── EventLoopFactory.h
β”‚   β”œβ”€β”€ UserSession/
β”‚   β”‚   β”œβ”€β”€ UserSession.h / .cpp
β”‚   β”‚   └── Connection.h
β”‚   β”œβ”€β”€ RAM/
β”‚   β”‚   β”œβ”€β”€ HashMap.h
β”‚   β”‚   └── HashMap.cpp
β”‚   β”œβ”€β”€ Storage/
β”‚   β”‚   β”œβ”€β”€ Persistence.h
β”‚   β”‚   └── Persistence.cpp
β”‚   β”œβ”€β”€ Worker/
β”‚   β”‚   β”œβ”€β”€ ThreadPool.h
β”‚   β”‚   β”œβ”€β”€ ThreadPool.cpp
β”‚   β”‚   β”œβ”€β”€ SnapshotScheduler.h
β”‚   β”‚   └── SnapshotScheduler.cpp
β”‚   β”œβ”€β”€ Limit/
β”‚   β”‚   β”œβ”€β”€ Limiter.h
β”‚   β”‚   └── Limiter.cpp
β”‚   └── Tests/
β”‚       β”œβ”€β”€ test_hashmap.cpp
β”‚       └── test_threadpool.cpp
β”œβ”€β”€ Dockerfile
β”œβ”€β”€ .dockerignore
β”œβ”€β”€ CMakeLists.txt
└── README.md

Roadmap

  • Custom HashMap with separate chaining
  • TCP server with Winsock2
  • Cross-platform networking support (Windows/Linux)
  • Command parser (INSERT, GET, DELETE)
  • AOF persistence with real-time logging
  • RDB snapshots every 5 minutes
  • AOF reset after each snapshot
  • Thread pool for concurrent client sessions
  • HashMap thread safety with shared_mutex
  • Persistence thread safety with mutex
  • Snapshot scheduler background thread
  • Clean server shutdown
  • Data recovery on restart (RDB + AOF replay)
  • Unit tests with GoogleTest (HashMap + ThreadPool)
  • Docker containerization (multi-stage Linux build)
  • Rate limiting with Token Bucket algorithm
  • Cross-platform event-driven architecture (epoll / IOCP)
  • Route idle-session socket cleanup through Server's connection teardown path
  • TCP fragmentation / message framing (LineBuffer)
  • Authentication (username + password)

License

This project is licensed under the MIT License. See LICENSE for details.


Built from scratch as a self-learning project to understand C++, networking, persistence, and systems programming.

About

simple key-value database made for educational proposes using C++, inspired by Redis.

Topics

Resources

License

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors