# kv-cache **Repository Path**: solidify-the-foundation/kv-cache ## Basic Information - **Project Name**: kv-cache - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-06-18 - **Last Updated**: 2026-06-23 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # kv-cache > 一条主线项目,从「单机 KV」逐步演进到「Raft 分布式 KV」,把 Go 高阶能力(并发、运行时调优、网络编程、共识算法、工程化)一次性练透。 > > 进度:**阶段 1 · 单机 KV + RESP 协议(进行中)** [English](./README.en.md) · 简体中文 --- ## 路线(5 个阶段) | 阶段 | 项目形态 | 核心练什么 | 状态 | |------|----------|-----------|------| | 0 | 工程骨架 | 项目布局、Makefile、CI、测试习惯 | ✅ | | 1 | 单机 KV + RESP 协议 | TCP、协议解析、io 组合、基础并发 | 🚧 | | 2 | 并发优化与淘汰策略 | 分段锁、sync.Pool、LRU/LFU、atomic | 待启动 | | 3 | 运行时调优与可观测 | pprof、逃逸分析、GC、benchmark、trace | 待启动 | | 4 | 持久化与崩溃恢复 | WAL、快照、fsync、文件 IO | 待启动 | | 5 | 分布式:Raft 复制 | 共识、状态机、超时重试、网络分区 | 待启动 | 完整路线说明请见仓库的 issue / 项目计划。 --- ## 当前能力(阶段 1) 兼容 Redis RESP2 协议的最小服务,支持用 `redis-cli` 直接连接。 支持命令: | 命令 | 说明 | |------|------| | `PING [msg]` | 健康检查 | | `ECHO msg` | 回显 | | `SET key value` | 写入(暂不支持 EX/PX/NX/XX 选项) | | `GET key` | 读取,不存在返回 nil bulk | | `DEL key [key ...]` | 删除,返回被删数量 | | `DBSIZE` | 当前 key 总数 | | `QUIT` | 服务端关闭连接 | | `COMMAND` | 返回空数组,仅为兼容 `redis-cli` 启动 | --- ## 目录结构 ``` . ├── cmd/kvd/ # 服务端二进制入口 ├── internal/ │ ├── resp/ # RESP2 协议编解码 + fuzz │ ├── store/ # KV 存储抽象 + 朴素 MemStore(阶段 1) │ └── server/ # TCP server + 命令分发 + 优雅关闭 ├── .github/workflows/ci.yml # GitHub Actions ├── .gitee/workflows/ci.yml # Gitee Go ├── .golangci.yml ├── Makefile └── go.mod ``` 设计上 `server` 只依赖 `store.Store` 接口,阶段 2 替换实现时无需改动调用方。 --- ## 运行 ### 前置 - Go 1.26+ - 可选:`golangci-lint`(lint 用) - 可选:`redis-cli`(功能验证用) ### 构建 & 运行 ```bash make build # 产物在 bin/kvd ./bin/kvd # 默认监听 127.0.0.1:6380 # 或直接 go run make run # 自定义参数 ./bin/kvd -addr :6380 -idle-timeout 1m -log-level debug ``` ### 用 redis-cli 验证 ```console $ redis-cli -p 6380 127.0.0.1:6380> PING PONG 127.0.0.1:6380> SET foo bar OK 127.0.0.1:6380> GET foo "bar" 127.0.0.1:6380> DEL foo (integer) 1 127.0.0.1:6380> GET foo (nil) ``` --- ## 开发 ```bash make test # 单元测试 + 集成测试 make race # -race 跑全量 make lint # golangci-lint make bench # 基准测试(阶段 2 起会有) make fuzz # RESP 解析器 fuzz(短跑 30s) make cover # 覆盖率 make all # lint + test + race + build ``` CI 会在每次 push / PR 上跑 build / test / race / lint,跑不过不许合并。 --- ## 阶段 1 的设计取舍 刻意保持「最朴素能跑通」的形态,把瓶颈留给后续阶段重构: - **每连接一 goroutine**:Go 网络编程的惯用法。事件循环要等到阶段 3 评估到延迟瓶颈再考虑。 - **`sync.RWMutex` + `map`**:一把大锁。阶段 2 改成分段锁后用 benchmark 量化提升。 - **每条命令立即 flush**:不做 pipeline 攒批。阶段 3 调优时再优化。 - **`Get` 返回拷贝**:API 上对调用方更友好;阶段 3 评估能否安全去掉这次拷贝。 测试相关: - RESP Reader 使用 `slowReader` 模拟逐字节投递,验证半包/粘包处理。 - RESP Reader 有 fuzz 入口 `FuzzReader`,保证任意输入不 panic、不死循环。 - Server 用 `127.0.0.1:0` 监听随机端口做端到端测试,避免端口冲突。 --- ## 后续阶段预告 - **阶段 2**:分段锁 / `sync.Map` / `atomic` 三套实现 + benchmark 对比;接入 LRU / LFU 淘汰;`sync.Pool` 复用 buffer。 - **阶段 3**:接入 `net/http/pprof`,跑火焰图找热点,README 贴 before/after 数据。 - **阶段 4**:WAL + 快照 + 崩溃恢复测试。 - **阶段 5**:Raft 选举 + 日志复制 + 网络分区测试。