ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

分布式协议之二 推荐一个raft协议的KV存储

分布式协议之二 推荐一个raft协议的KV存储 NeoKV 概述概览NeoKV 是什么、为什么做这个项目系统架构两种进程、Region、请求链路与 Redis Cluster、Kvrocks、Pika 的定位差异构建、运行、学习路线NeoKV 是一个基于BraftMulti-Raft RocksDB的分布式强一致 KV 存储对外提供Redis 兼容协议RESP。你可以直接用redis-cli或任何 Redis SDK 连接它执行 SET、GET、HSET、ZADD 这些你熟悉的命令——底层的 Raft 共识和 RocksDB 持久化对客户端完全透明。这是一个面向教学的项目。我们的目标不是做一个生产级的 Redis 替代品而是通过实际的工程实践来回答两个核心问题如何用 Multi-Raft 实现强一致的分布式存储以及如何在 RocksDB 这样的 KV 引擎上高效地实现 Redis 的丰富数据结构代码不是从零开始的。在分布式架构上我们参考了 BaikalDB 的 Multi-Raft 和 Region 管理设计在 Redis 数据结构的 KV 编码上我们借鉴了 Apache Kvrocks 和 Pika 的思路。站在这些优秀项目的肩膀上让我们可以集中精力在最核心的问题上。注意NeoKV 是学习项目不适用于生产环境。系统架构NeoKV 由两类进程组成——MetaServer集群管理和Store数据服务┌────────────────────────────────────────────────┐ │ neoMeta (Cluster) │ │ │ │ ┌───────────┐ ┌───────────┐ ┌───────────┐ │ │ │ MetaNode1 │ │ MetaNode2 │ │ MetaNode3 │ │ │ └───────────┘ └───────────┘ └───────────┘ │ │ Raft HA / Region Scheduling / Schema / TSO │ └───────────────────────┬────────────────────────┘ │ Heartbeat Scheduling ┌───────────────┼───────────────┐ ▼ ▼ ▼ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │ neoStore1 │ │ neoStore2 │ │ neoStore3 │ │ │ │ │ │ │ │ ┌──────────┐ │ │ ┌──────────┐ │ │ ┌──────────┐ │ │ │ Region 1 │ │ │ │ Region 1 │ │ │ │ Region 1 │ │ │ │ (Leader) │◄┼─┼─┤(Follower)│ │ │ │(Follower)│ │ │ ├──────────┤ │ │ ├──────────┤ │ │ ├──────────┤ │ │ │ Region 2 │ │ │ │ Region 2 │ │ │ │ Region 2 │ │ │ │(Follower)│ │ │ │ (Leader) │ │ │ │(Follower)│ │ │ └──────────┘ │ │ └──────────┘ │ │ └──────────┘ │ │ RocksDB │ │ RocksDB │ │ RocksDB │ │ brpc Redis│ │ brpc Redis│ │ brpc Redis│ └──────────────┘ └──────────────┘ └──────────────┘neoMeta入口src/meta_server/main.cpp负责集群元数据管理Region 分配与调度、Schema 管理、TSO 时间戳服务。MetaServer 自身通过 Raft 实现高可用不依赖外部的 ZooKeeper 或 etcd。neoStore入口src/store/main.cpp是数据服务节点承载多个 Region每个 Region 是一个独立的 Raft 组。每个 Store 节点暴露两个端口brpc 端口--store_port用于内部 Raft 通信和 Store 间 RPCRedis 端口--redis_port默认 16379运行brpc::RedisService对外提供标准的 RESP 协议。此外还有一个单进程测试模式——neo_redis_standalonesrc/redis/neo_redis_standalone.cpp内嵌 RocksDB 单副本 Raft Region无需 MetaServer用于本地开发和集成测试。核心概念在深入具体章节之前先了解几个贯穿全书的核心概念。Region是数据分片的基本单位。每个 Region 管理一段连续的 Redis Slot 范围0-16383是一个独立的 Raft 组三副本分布在不同 Store 节点上。Region 可以自动分裂Split和合并Merge这让集群能够根据数据量和负载动态调整。Slot是 Redis Cluster 的哈希槽概念。每个 Redis key 通过 CRC16 算法映射到 0-16383 中的一个 slotslot 再映射到 Region。NeoKV 兼容 Redis Cluster 的 slot 机制支持 Hash Tag 和 MOVED 重定向。Column FamilyCF是 RocksDB 中逻辑隔离的 KV 命名空间。NeoKV 使用 8 个 CF 分别存储 Raft 日志、数据、元信息等每个 CF 可以独立配置 compaction 策略和压缩算法。Raft 共识是 NeoKV 的核心保证。所有写操作必须经过 Raft 共识多数节点确认才能提交保证强一致性。读操作可以直接读本地 RocksDBLeader也可以通过 ReadIndex 协议在 Follower 上保证一致性读。请求链路一个 Redis 命令从客户端发出到最终返回结果经历以下路径Redis Client (redis-cli / SDK) │ RESP 协议 ▼ brpc::RedisService (neoStore 进程, port 16379) │ brpc 框架完成命令解析 ▼ CommandHandler (GetCommandHandler / SetCommandHandler / ...) │ ├── 读路径 │ RedisRouter::route() → 定位 Region │ │ │ ├─ Leader: 直接本地读 RocksDB │ ├─ Follower (ReadIndex): 向 Leader 确认 committed │ │ index等待本地 apply 追上后读取 │ └─ Follower (无 ReadIndex): 返回 MOVED 重定向 │ └── 写路径 RedisRouter::route() → 定位 Region │ ▼ 构建 RedisWriteRequest (protobuf) │ ▼ braft::Node::apply(task) ── Raft 共识多数节点确认 │ ▼ Region::on_apply() → apply_redis_write() │ ▼ RocksDB WriteBatch (原子写入)这里有一个关键的设计决策写入必须经过 Raft 共识。这是 NeoKV 与 Kvrocks、Pika 等系统的本质区别。后者直接写 RocksDB通过异步主从复制保证可用性NeoKV 的每一次写入都经过多数节点确认保证强一致性。一旦告诉客户端写入成功这条数据就不会丢失——即使 Leader 随后立刻宕机新选举出的 Leader 一定包含这条数据。定位与对比理解 NeoKV 的定位最好的方式是和同类系统做对比。Redis Cluster是 Redis 官方的集群方案。数据存在内存中通过异步主从复制保证可用性16384 个 slot 手动或半自动迁移。它的优势是极致的内存性能劣势是数据一致性为最终一致——主从切换窗口期可能丢数据。Kvrocks和Pika是两个知名的持久化 Redis 替代品。它们用 RocksDB 替代内存作为存储引擎解决了数据量超过内存的问题。但它们的复制仍然是异步 Binlog 复制一致性保证与 Redis 相同——最终一致。NeoKV 走了一条不同的路Raft 强一致 RocksDB 持久化 Region 自动分裂合并。代价是写入延迟更高需要多数节点确认但换来的是线性一致性的保证。它不是一个缓存系统而是一个分布式存储只是恰好兼容 Redis 协议。当然NeoKV 是教学项目不是生产系统。和上面三者相比它缺少很多生产级特性完整的监控、在线扩缩容工具链、性能调优等。但正因为是教学项目我们可以在代码中保持清晰的结构和充分的注释让学习者能够看懂每一个设计决策背后的权衡。已实现功能NeoKV 实现了98 个 Redis 命令覆盖五种数据类型String19 个、Hash15 个、Set17 个、List14 个、ZSet17 个加上 13 个 Key 操作命令DEL、EXPIRE、TTL 系列等和 3 个通用命令PING、ECHO、CLUSTER。完整的命令列表和语法说明见 附录命令参考。分布式特性方面Multi-Raft 共识每个 Region 独立的 Raft 组、Region 自动分裂与合并、Follower ReadIndex 强一致读、MOVED 重定向兼容 Redis Cluster 协议、CLUSTER SLOTS / NODES / INFO / KEYSLOT / MYID、以及后台 TTL 清理。项目结构NeoKV/ ├── src/ │ ├── common/ # 公共工具Key 编码、Schema 缓存、RPC 客户端 │ ├── engine/ # 存储引擎RocksWrapper、QoS、Compaction Filter │ ├── meta_server/ # MetaServer集群管理、Region 调度、TSO │ ├── raft/ # Raft 定制层自定义 Log/Meta Storage、Snapshot Adaptor │ ├── raft_meta/ # MetaServer 的 Raft 回调实现 │ ├── raft_store/ # Store 的 Raft 回调实现 │ ├── redis/ # Redis 协议层NeoKV 核心新增 │ │ ├── redis_service.cpp # 命令处理器98 个命令的 Handler │ │ ├── redis_router.cpp # Slot 路由CRC16、CROSSSLOT、MOVED │ │ ├── redis_codec.cpp # Phase 1 Key/Value 编码 │ │ ├── redis_metadata.cpp # Phase 2 Metadata 编码移植自 Kvrocks │ │ ├── region_redis.cpp # Raft apply 逻辑所有写命令的执行 │ │ ├── redis_ttl_cleaner.cpp # TTL 后台清理 │ │ └── neo_redis_standalone.cpp # 单进程测试模式入口 │ └── store/ # Store 节点Region 管理、Raft 状态机 ├── include/ # 头文件与 src/ 镜像结构 ├── proto/ # Protobuf 定义Raft 消息、Store RPC、Redis 命令 ├── test/ # C 单元测试GTest ├── tests/gocase/ # Go 集成测试基于 go-redis ├── conf/ # 配置文件 ├── cmake/ # CMake 模块 └── book/ # 文档你正在阅读的内容如果你想快速找到某个功能的实现有几个入口值得记住redis_service.cpp是所有 Redis 命令 Handler 的注册和实现超过 90% 的命令是怎么处理的问题都可以从这里找到答案。region_redis.cpp是 Raft apply 层的 Redis 写命令执行逻辑——Handler 通过 Raft 提交请求后最终的执行都在这里。redis_metadata.h和redis_metadata.cpp定义了所有数据类型的存储编码格式。构建与快速上手构建mkdir -p build cd build cmake -DWITH_TESTSON .. make -j$(nproc)构建产物在build/output/bin/目录下。启动 Standalone 模式——最快的体验方式不需要部署集群./build/output/bin/neo_redis_standalone --redis_port16379 --data_dir/tmp/neokv_standalone等待NEOKV_READY标记输出后服务就绑了。验证redis-cli -p 16379 PING # → PONG redis-cli -p 16379 SET hello world redis-cli -p 16379 GET hello # → world redis-cli -p 16379 HSET user:1 name Alice age 30 redis-cli -p 16379 HGETALL user:1运行测试# C 单元测试 cd build make test ​ # Go 集成测试 cd tests/gocase mkdir -p workspace go test -count1 ./unit/... \ -args \ -binPath$(pwd)/../../build/output/bin/neo_redis_standalone \ -workspace$(pwd)/workspace学习路线我们建议按以下顺序阅读。每一部分都建立在前一部分的基础上从底层共识一路向上到协议层最后看测试如何验证这一切的正确性。路线一完整学习推荐Part 1 — Multi-Raft 分布式架构从 Raft 共识算法开始理解 braft 框架的使用与定制深入 Region 状态机和集群管理。这是 NeoKV 的核心。Part 2 — 存储引擎理解 RocksDB 的关键特性以及 NeoKV 如何组织 8 个 Column Family、设计 Key 编码、实现 Redis 数据结构的存储。Part 3 — Redis 数据结构逐一了解 String、Hash、Set、List、ZSet 五种数据类型在 RocksDB 上的编码与实现。Part 4 — Redis 协议层理解 RESP 协议接入、命令路由、TTL 过期机制。Part 5 — 测试与运维了解测试体系学习如何验证和扩展功能。路线二专注分布式00-概述 → 01-Raft 共识算法 → 02-braft 实践 → 03-Multi-Raft 与 Region → 04-MetaServer 与集群管理路线三专注存储00-概述 → 05-RocksDB 基础 → 06-存储架构设计 → 07-Redis 存储编码 → Part 3 任意章节
返回列表