Skip to content

Latest commit

 

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

KVStore

一个从零实现的轻量级键值存储系统,代码结构清晰、注释完整,适合学习 Redis 底层原理和网络编程。

单实例 pipeline 模式 QPS 可达 19w,基于 jemalloc 内存分配器,支持二进制安全存储。

特性

  • 高性能网络:基于 epoll 的单线程 Reactor 模型,无锁设计,轻松应对高并发连接。
  • RESP 协议:完整实现 Redis 序列化协议,可直接用 redis-cli / redis-benchmark 访问。
  • 二进制安全:哈希表和协议层均使用显式字节长度 + memcpy,key/value 可包含任意字节(含 \0)。
  • 持久化:支持 AOF 日志、RDB 快照、混合模式三种策略,通过配置文件一行切换。
  • 主从复制:全量同步(FULLSYNC)+ 增量命令广播 + 断线自动重连。
  • 大 value 支持:读写缓冲区按需动态扩容,无大小硬限制。
  • 配置管理:INI 格式配置文件 + 命令行参数,命令行优先级更高。
  • 日志分级:INFO / WARN / DEBUG 三级,可在配置文件中调整。

快速开始

# 1. 克隆并编译
git clone https://github.com/NeilYuan0404/kvstore.git
cd MyKvstore
make

# 2. 启动服务(自动加载 conf/kvstore.conf)
./bin/kvstore

# 3. 用 redis-cli 连接
redis-cli -p 6379
> SET hello world
+OK
> GET hello
"world"
> DEL hello
:1

调试模式(开启详细日志 + AddressSanitizer):

make DEBUG=1
./bin/kvstore

命令参考

命令 语法 说明
SET SET <key> <value> 写入键值对,key 已存在则覆盖
GET GET <key> 读取键值,不存在返回 $-1
DEL DEL <key> 删除键,返回删除数量
EXISTS EXISTS <key> 检查键是否存在,返回 0/1
MOD MOD <key> <value> 仅当键存在时更新值
SAVE SAVE 手动触发 RDB 快照保存
PING PING [message] 连通性探测,返回 PONG 或回显 message

启动参数

./bin/kvstore [选项]

  -p <port>              监听端口(覆盖配置文件)
  -c <path>              指定配置文件路径
  --persist-mode <0-3>   持久化模式(覆盖配置文件)
  --slaveof <ip> <port>  以从机身份启动,连接指定主机

优先级:命令行参数 > 配置文件 > 内置默认值

目录结构

MyKvstore/
├── bin/                  # 编译产物(kvstore 可执行文件)
├── conf/
│   └── kvstore.conf      # 主配置文件
├── data/                 # 持久化数据目录(.rdb / .aof)
├── dep/
│   └── jemalloc/         # 内存分配器依赖
├── doc/
│   ├── overall.excalidraw  # 整体架构图
│   ├── persist.md          # 持久化模块设计
│   └── replication.md      # 复制模块设计
├── include/              # 公共头文件
│   ├── kvstore.h           # 顶层宏定义
│   ├── server.h            # Reactor 连接结构体
│   ├── kvs_base.h          # 内存分配封装
│   ├── kvs_hash.h          # 哈希表接口
│   ├── kvs_persist.h       # 持久化接口
│   ├── kvs_replication.h   # 复制接口
│   └── kvs_configure.h     # 配置管理接口
├── src/
│   ├── reactor.c           # epoll Reactor 事件循环
│   ├── kvstore.c           # RESP 协议解析 + 命令执行
│   ├── kvs_hash.c          # 哈希表存储引擎
│   ├── kvs_persist.c       # AOF / RDB 持久化
│   ├── kvs_replication.c   # 主从复制
│   └── kvs_configure.c     # 配置文件解析 + 日志
├── test/
│   └── scripts/            # Shell 集成测试套件
└── Makefile

架构概览

客户端 (redis-cli)
       │ RESP 协议
       ▼
┌─────────────────────────────────────────────┐
│              reactor.c                      │
│  epoll 事件循环 — 单线程,无锁              │
│  accept_cb → recv_cb → send_cb             │
└───────────────┬─────────────────────────────┘
                │ 解析后的字节流
                ▼
┌─────────────────────────────────────────────┐
│              kvstore.c                      │
│  parse_resp()  RESP array 解析             │
│  kvs_executor() 命令分发                   │
└──────┬─────────────┬────────────────────────┘
       │             │
       ▼             ▼
┌──────────┐  ┌──────────────┐  ┌──────────────┐
│ kvs_hash │  │ kvs_persist  │  │kvs_replication│
│ 哈希存储 │  │ AOF / RDB    │  │ 主从复制      │
└──────────┘  └──────────────┘  └──────────────┘

关键设计决策

  1. 协议识别推迟到 kvs_protocol:所有连接在 accept 时统一走 event_register,PSYNC 握手在协议层而非 accept 层识别,避免特殊分支。
  2. 二进制安全贯穿全层:从 RESP $N\r\n 头到哈希表 memcpy,任意字节均可安全存储。
  3. 从机回放防循环:从机用 g_is_loading = true 包裹 kvs_protocol,防止回放 master 命令时再次触发 kvs_replication_feed_slaves 形成广播环路。
  4. 非阻塞连接安全握手kvs_connect_master 使用 poll(POLLOUT) 等待 TCP 三次握手完成,再发 PSYNC,避免在 EINPROGRESS 状态下 send 静默失败。

配置文件说明

# conf/kvstore.conf

[server]
port = 6379
log_level = 1          # 1=INFO  2=WARN  3=DEBUG

[persist]
mode = 3               # 0=关闭  1=仅AOF  2=仅RDB  3=混合(默认)
rdb_file = ../data/kvstore.rdb
rdb_save_interval = 300      # RDB 自动保存间隔(秒)
rdb_min_changes = 100        # 触发自动保存的最少变更数
rdb_save_on_shutdown = true  # 关闭时是否保存 RDB
aof_file = ../data/kvstore.aof
aof_rewrite_size = 1         # AOF 自动重写阈值(MB)
aof_auto_rewrite = true

[replication]
enabled = false        # 开启主从复制
role = master          # master 或 slave
# master_ip = 127.0.0.1
# master_port = 6379

配置文件搜索顺序(优先级递减):

  1. 命令行 -c 指定路径
  2. ./kvstore.conf(当前目录)
  3. ./conf/kvstore.conf(项目目录)
  4. ~/.kvstore.conf
  5. /etc/kvstore.conf

测试

# 运行所有集成测试
./test/scripts/run_all_tests.sh

测试套件覆盖:

脚本 测试内容
test_aof.sh AOF 持久化写入与重放
test_rdb.sh RDB 快照保存与恢复
test_large_value.sh 大 value 读写(最大 100 KB)
test_special_chars.sh UTF-8、Emoji、特殊符号二进制安全测试
test_replication_master.sh 主机写入同步至从机(全量 + 增量 + 删除)
test_replication_slave.sh 从机连接与数据接收

性能测试

# Pipeline 模式(16 条命令/批次)
redis-benchmark -p 6379 -P 16 -n 200000 -t set,get

# 100 并发客户端
redis-benchmark -p 6379 -c 100 -n 100000 -t set,get

贡献指南

注释规范

  • 公共函数:在函数上方用块注释说明用途、参数、返回值和注意事项。
  • 注释优先解释 why,而非 what(代码本身说明 what)。
  • 复杂逻辑块:必须有 1-2 句解释背景或限制条件。
  • 使用统一标记:TODO: 未完成功能 / FIXME: 已知问题 / NOTE: 重要约束。

提交前检查

make          # 确保编译无警告
./test/scripts/run_all_tests.sh   # 确保所有测试通过

作者

Neil Yuan · v1.2.0

About

基于EPOLL的轻量级高性能kv存储项目,可对接博客存储、用户信息缓存、短连接系统后台应用。支持内存池,持久化和主从同步,特殊字符和大value兼容。可redis resp指令操作。redis-benchmark实测,裸奔时单机QPS达19w+

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages