展开菜单
首页 精品内容 本月促销 装机必备 Windows PDF教程 macOS软件 IOS软件 Android AI 专题
全部分类

当前位置:

首页 > 编程开发 > 【AdvisKV】#01: 关于我从零写一个 C++ 分布式 KV 存储系统原型

【AdvisKV】#01: 关于我从零写一个 C++ 分布式 KV 存储系统原型

日期: 2026.7.6 写在开头的开头 AdvisKV 是我用 C++17 从零写的一个分布式 KV 存储系统原型,包含 Meta、SDM、Storage、SDK 四个主要模块,覆盖建库建表、路由查询、KV 读写、副本数扩缩容、坏副本替换、Raft、WAL/snapshot 恢复,跑了gtest

本文目录

    日期: 2026.7.6

    写在开头的开头

    AdvisKV 是我用 C++17 从零写的一个分布式 KV 存储系统原型,包含 Meta、SDM、Storage、SDK 四个主要模块,覆盖建库建表、路由查询、KV 读写、副本数扩缩容、坏副本替换、Raft、WAL/snapshot 恢复,跑了gtest + E2E 测试和 benchmark。(但是控制面高可用、自动 rebalance、接入rocksdb这些还没实现)

    写在开头

    算算日子,又是大半年没更新博客了。上次动笔还是 OB 复赛结束后,写的一篇凄凄惨惨的总结文,一晃半年就这么过去了。简单交代下背景吧。比赛结束后,开始准备找实习。本来以为会很难,结果面了五六家,从字节基架到 OB 数据库内核,再到一些游戏引擎、自动驾驶的小厂,主要为了刷刷经验值。最初想投字节给 OB 的面试攒点底气,没想到字节效率高得离谱,没几天就发了 offer。最后纠结了一下,害怕一头扎进数据库内核把路走窄了,想了想,还是去基础架构试试。

    实习差不多一个月,发现自己能学到的东西有限,实际代码开发少得可怜,每天基本就是排查问题、改点简单的代码、跑跑性能测试。心里开始犯嘀咕:照这个节奏下去,到秋招怕不是要废了。组内核心项目又不可能让我上手写代码,总得自己找点事干。巧的是,组里的项目恰好是分布式 KV,于是就想:不如把这套逻辑搞明白,自己从头写一个分布式 KV 出来。至少以后面试被问到实习做了什么,还能理直气壮地说自己私下撸了个分布式 KV,也不算白来一趟。

    有点尴尬的是,自己设定的场景和组内项目差异太大,加上 V1 版本功能上没法实现得很全面,最后魔改一通,除了模块名字,几乎和组内的项目没什么关系了。

    以上就是写出 AdvisKV 的初衷。说白了,多少也抱着想做出一个自己代表作的心态。毕竟之前写的那些 rmdb、miniob、seekdb 的代码,严格来说都不算是我自己的项目。

    开始写这篇文档的时候,项目已经基本上完成得差不多了——至少 benchmark 能完整跑通(笑)。当时想着架构应该不会再大改了,顶多后期优化下性能,删掉那些乱七八糟的注释,可以动笔了。当然,后来的事实证明我又重构了很多次。

    AdvisKV 是什么

    简单说,AdvisKV 是我用 C++17 写的一个分布式 KV 存储系统原型,一个学习向的系统原型。说白了,就是给自己的秋招简历加点料。同时也希望完成第一个从头干到尾的项目。期望别太高,定位就是一个学习原型。

    如果概括这个项目的主线,大概是:Meta/SDM 作为控制面维护表、副本和路由的期望状态,Storage 作为数据面负责 KV 读写和 Raft 复制,控制面和数据面通过心跳和 reconciler 不断把系统状态收敛到预期。

    整个项目分成四个模块:

    • Meta 负责 DB、Table 这些元数据和 DDL。
    • SDM 负责 Storage 节点注册、心跳、ReplicaGroup 编排、期望副本下发和 Route 维护。
    • Storage 负责 KV 数据读写、Raft 和本地持久化。
    • SDK 对外提供基于 db + table + key 的 put/get/delete 接口。

    目前可以跑通建库建表、路由查询、KV 读写、副本数调整、自动替换坏副本、Raft、WAL、snapshot、recover 等功能。有两百多个 gtest 单测,一批 E2E 测试(比如最基础的端到端 KV 链路、leader 崩溃后切主、follower 追日志和追 snapshot、Meta/SDM 重启恢复等),还有 benchmark 和 metrics。

    详细的实现数据和 benchmark 就不在这里展开了。关于这个项目,我更想写的是自己做下来的感受——也一直都是这个风格,所以就不搞太官方的味道了。

    Show

    这个分布式 KV 的数据模型和正常的数据库差不多,有 db、table 的概念。

    用户可以创建自己的 DB,然后在 DB 里面创建 table。每个 table 在创建时可以指定 shard 数和 replica 数。一个 table 会被拆成多个 shard,每个 shard 又会有多个 replica。需要说明一下,V1 版本里 shard 数是在创建 table 时确定的,后续暂时不能动态修改;replica 数现在可以通过 alter_table 调整,也支持缩到 0 再扩回来。也就是说,目前不是完全没有扩缩容,只是支持了副本数这条链路,自动 rebalance 和 shard 数变更还没做——以后大概率也不会做了,这个项目应该到此为止了。

      
    # 项目里提供了一个交互式 CLI adviskvctl,方便演示
    # 建库建表
    adviskv> create_db demo_db dc1
    OK db_id=1
    
    # create_table    
    adviskv> create_table demo_db demo_table 4 3 default
    OK table_id=1
    
    # wait_table  
    [timeout_ms] adviskv> wait_table demo_db demo_table OK table_state=NORMAL # put
    adviskv> put demo_db demo_table hello world OK # get
    adviskv> get demo_db demo_table hello OK value="world" adviskv> delete demo_db demo_table hello OK # route
    adviskv> route demo_db demo_table hello Route table: demo_db.demo_table key: hello shard: table_id=1 shard_id=2 replicas: - replica_id=1:2:0 endpoint=127.0.0.1:50051 role=LEADER - replica_id=1:2:1 endpoint=127.0.0.1:50052 role=FOLLOWER - replica_id=1:2:2 endpoint=127.0.0.1:50053 role=FOLLOWER # key hello 会先定位到 table 某个 shard,然后 SDK 再通过 SDM 查询该 shard 对应的 route,通过 endpoint 把请求发送到对应的 leader 的 Storage 节点 # 副本的扩缩容 # alter_table
    adviskv> alter_table demo_db demo_table 2 OK table_id=1 replica_count=2

    目前支持的操作是最基本的同步 put、get、delete。这些操作交给 SDK 模块处理。可以创建一个 KVClient 进行 put、get 等操作。顺带一提,CLI 里面命令可以写 delete,SDK 里对应的方法名叫 del。

    SDK 的使用方式:

      
    #include 
    #include "sdk/client.h"
    
    int main() {
        adviskv::sdk::KVClientConf conf;
        conf.db_name = "demo_db";
        conf.table_name = "demo_table";
        conf.sdm_host = "127.0.0.1";
        conf.sdm_port = 50049;
        conf.sdm_timeout_ms = 3000;
        conf.storage_timeout_ms = 3000;
    
        adviskv::sdk::KVClient client(conf);
    
        adviskv::Status put_status = client.put("hello", "world");
        if (put_status.fail()) {
            std::cerr << put_status.to_string() << std::endl;
            return 1;
        }
    
        adviskv::Value value;
        adviskv::Status get_status = client.get("hello", &value);
        if (get_status.ok()) {
            std::cout << value << std::endl; // value:"world"
        }
    
        return 0;
    }
      
    

    Minimal Overview

    整体架构的粗略介绍

    项目分为四个模块:meta、sdm、storage、sdk。

    SDK

    先聊聊最外层的 SDK。SDK 本身并不算分布式 KV 的服务端模块,就是一个客户端库,给使用者执行 put、get 这类操作。

    拿 put 操作来说,在当前版本里,SDK 会先向 SDM 查询 route,也就是路由表。这个 route 包含当前 db/table 对应的 shard 信息,以及每个 shard 下面的 replica 节点信息。SDK 根据 key 算出它落在哪个 shard 上,然后从这个 shard 的 replica 列表中找到 leader 节点,直接给这个节点发送 put 操作。删除操作也是这个流程。V1 版本里,get 操作也只有 leader 才能执行,后续版本可能会优化这块。

    Meta

    Minimal architecture diagram:

    Meta 模块负责 DDL 和 DB/Table 这些元信息。

    创建 table 时,请求先打到 Meta。Meta 收到 CreateTable 之后,先在自己的 catalog 里记录这个 table,并把状态标记成“创建中”。然后 Meta 向 SDM 发送 PlaceTable 请求,让 SDM 负责后续的 replica 放置和 route 生成。

    注意一点:CreateTable 返回成功并不代表 table 立刻就可以读写。这个接口本身是异步的,返回 OK 只代表 Meta 接受了这个 DDL,不保证 DDL 最终成功。table 是否真正 ready,取决于 Meta 和 SDM 里的后台 reconciler 能否把状态推进到最终状态。

    后面加上了副本数调整功能,这里多了 AlterTableReplicaCount。用户发起 alter_table 时,Meta 先把 catalog 里的 replica_count 和状态改掉,然后通知 SDM 去把每个 shard 的目标副本数调到新值。这个过程也不是同步等所有 replica 调整完,最终还是靠后台 reconciler 推回来。

    创建 DB 这类操作就不会发送给 SDM,因为 DB 是只有 Meta 才会知道的概念,SDM 不会在乎 DB,也不会持久化它。SDM 只关心 table,以及对应的 shard_count 和 replica_count 来进行编排。虽然 SDK 通过传递 db_name、table_name 和 hash(key) 找到路由表,但 db_name 实际上是附在 table 上的,所以不需要 SDM 知道 DB 的存在,它只需要了解 table 的内容就够了。

    SDM

    Minimal architecture diagram:

    SDM 维护了一个非常重要的东西:route。route 以 shard 为单位,每个 shard 都有一个对应的 route。SDK 每次做 put/get/delete 时,先拿 db_name 和 table_name 去 SDM 查询路由表,然后根据 key 算出对应的 shard,再从 shard 的 replica 列表中找到 leader 节点,最后把真正的 KV 请求发给 storage。

    另外,SDM 还负责 storage 节点的注册和心跳。Storage 启动后,向 SDM 注册自己,然后周期性发送 heartbeat。Heartbeat 不只是告诉 SDM 节点还没掉线,还会把本机 replica 的状态、raft role、成员信息(leader 会传)等发过去;SDM 也在 heartbeat response 里下发期望的 Replica,让 storage 的 NodeAgent 在本机创建、删除 replica,或者做成员变更。SDM 和 storage 这边用的是经典的“观测-期望”模式:SDM 维护期望状态,让 NodeAgent 去收敛。自动 rebalance 的话就没再做了——再搞也赶不上秋招了。

    另外,SDM 需要提供 route,SDK 的链路是通过 db_name + table_name + key 向 SDM 查询路由表。所以 SDM 需要了解 table 的概念,也需要知道每个 table 下面有多少个 shard。Table 里面还有 ReplicaGroup 这一层,每个 shard 对应一个 group,用来维护这个 shard 希望有几个副本、哪些 replica 是当前还想保留的成员。Shard 作为逻辑数据,并没有在 SDM 里专门出现,而是通过 ReplicaGroup + Route 的方式在代码层面实现。

    由于用了经典的“观测-期望”,后台任务目前主要靠几类后台 reconcile 去推动状态:TableReconciler 负责判断 table 是否 ready/deleting,ReplicaGroupReconciler 负责根据 target_replica_count 去补副本、删副本、替换坏副本,Route 负责在 replica ready 之后发布可用路由。说起来有点绕,但核心想法就是不断对齐“应该是什么样子”和“现在实际是什么样子”。后面讲到 SDM 的时候再细说。

    Storage

    Minimal architecture diagram:

    Storage 负责数据的读写。前面的 Meta 和 SDM 更偏控制面,一个管元信息,一个管路由和节点状态;Storage 这边是真正处理 put/get/delete 请求,以及维护数据副本的地方。

    拿 put/delete 操作来说,SDK 直接把请求打到对应 shard 的 leader 所在的 storage 节点上。写请求打到 storage 后,进入 replica 内部,交给 Raft 做复制。首先本地写一条 Raft log,然后发送给其他 follower,等待这条 log 被多数派确认并提交之后,会 apply 到 KV engine。当前版本的 KV engine 还是简单的 map engine,主要是先把分布式链路跑通。后续有考虑接 rocksdb,不过还只是“maybe”。

    get 操作目前也是 leader-only 的状态,最终读请求只会打到 leader 上。不过加了一个读一致性机制,读之前会确认自己仍然是合法 leader,并确保本地状态机至少 apply 到对应的 read index,避免读到旧 leader 或者还没 apply 完的状态。

    此外,Storage 还做了 WAL 和 snapshot 相关的持久化逻辑。当前实现里,WAL 主要承载 Raft log,用来记录每个 replica 的写入日志;snapshot 则保存已经 apply 之后的 KV 状态。服务重启时,可以通过 snapshot 加上后续 WAL 恢复 replica 状态。

    V1的局限

    还有很多没完成的内容,包括:

    • Meta 和 SDM 在 V1 版本里只跑单进程,没有高可用。
    • Storage 侧的 KV engine 直接用了 map,还没接 rocksdb。
    • Shard 不支持 split,也没有实现自动 rebalance。
    • 目前只支持 leader 的 put 和 read,不支持 follower read。

    写在最后

    最早写完这篇博客是在 6 月 12 号,但后来又做了大规模的重构,并且加上了扩缩容功能——为了这个功能重构了好多东西,拖到现在已经一个月了。为什么非要支持扩缩容?当时想着把项目收尾,了解到了 tinykv 这个项目,发现它的完全体几乎是全方面吊打我的项目,悲痛欲绝之下,想着怎么也得再多实现一个功能吧,不然也太小丑了。(如果再给我一次机会,可能不会写这个项目了,直接去实现 tinykv 不香吗……)

    总的来说,大体上把项目介绍了一下。这个项目完成得不算好,应该有很多设计不太合理的地方。毕竟没有系统学习过分布式,很多内容都是边看、边查、边问、边写出来的。很多设计甚至一开始并没有想清楚,经常写到一半发现不对,再慢慢修修补补出来。

    如果有同学抱着学习分布式 KV 的目的来看这个项目,发现某些设计看起来很别扭,那大概率不是你理解错了,很可能就是这里还没设计好。后面的文章里,我也会尽量把这些地方讲清楚,包括哪些是当前版本的取舍,哪些是后续应该继续改进的地方。

    这篇就作为 AdvisKV 文档系列的开坑文,暂且写到这里吧。to be continue。

    本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系bd@zhengruan.com
    作者最新文章
    编程开发
    相关文章 更多
    精品专题 更多
    装机必备

    正软商城装机必备专区,精选办公、浏览器、安全防护、影音播放、压缩解压、设计创作和系统工具等电脑常用正版软件,帮助用户快速完成新电脑软件配置。

    Windows

    正软商城Windows软件专区,汇集适用于Windows电脑的办公、设计、安全防护、影音播放、开发工具和系统优化软件,提供软件介绍、系统要求、正版授权及购买下载服务。

    PDF教程

    正软商城PDF教程频道提供PDF编辑、转换、合并、拆分、压缩及格式处理方法,同时介绍常用PDF软件和工具的使用技巧。

    macOS软件

    正软商城macOS软件专区,精选适用于Mac电脑的办公、设计、影音、效率、开发和系统工具,提供软件功能介绍、macOS兼容版本、正版授权及购买下载服务。

    IOS软件

    正软商城iOS软件专区,精选适用于iPhone和iPad的办公、学习、影音、设计、效率及AI应用,提供功能介绍、适用设备、系统要求和正版获取方式等信息。

    AI

    正软商城AI软件专区,汇集AI写作、AI绘画、AI视频、AI办公、AI编程、AI翻译、智能客服和数据分析等人工智能工具,提供功能介绍、适用平台、收费方式及正版购买信息。

    Mac软件 更多
    Aperty macOS版
    Aperty macOS版

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw macOS版
    AionClaw macOS版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy macOS版
    Loomy macOS版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    AirBuddy 3 macOS版
    AirBuddy 3 macOS版

    AirBuddy 3 是面向 macOS 的蓝牙外设增强工具,可集中查看 AirPods、Beats 与苹果设备电量,提供快速连接、播放控制、电量提醒、桌面小组件和多台 Mac 外设接力等功能。

    AirServer macOS版
    AirServer macOS版

    AirServer macOS版可把 Mac 转换为无线投屏接收端,通过 AirPlay 或 Google Cast 接收手机、平板和电脑画面,并支持多设备同时连接、高清镜像及会话录制,适合家庭娱乐、课堂教学、会议演示和应用展示。

    AnyDesk macOS版
    AnyDesk macOS版

    AnyDesk macOS版是一款适用于远程办公、设备维护和客户支持的远程桌面工具,可连接并操作异地计算机,支持文件传输、无人值守访问、会话权限控制及跨平台协作。

    WINDOWS 更多
    讯飞绘文 网页版
    讯飞绘文 网页版

    讯飞绘文网页版是科大讯飞推出的AI图文创作与内容运营工具,覆盖热点选题、文章生成、稿件校对、智能配图、排版发布和数据复盘等环节,适合自媒体创作者及内容团队在线使用。

    Maya(Autodesk Maya) Windows版
    Maya(Autodesk Maya) Windows版

    Autodesk Maya 是面向影视、电视、动画和游戏行业的专业三维制作软件,集多边形与 NURBS 建模、角色绑定、关键帧和动作捕捉动画、Bifrost 特效模拟、材质开发及 Arnold 渲染于一体,

    Aperty Windows版
    Aperty Windows版

    Aperty 是 Skylum 推出的 AI 人像修图软件,支持自然肤质修饰、瑕疵处理、面部与身体调整、预设及批量同步。

    火山引擎 网页版
    火山引擎 网页版

    火山引擎是字节跳动旗下企业级云与AI服务平台。聚焦大模型核心能力,依托字节自研豆包多模态大模型,凭借火山方舟一站式平台,提供模型精调、推理部署、智能应用搭建等全链路服务,结合高性能AI算力,助力各行业快速落地大模型数字化与智能化应用。

    立刻MV 网页版
    立刻MV 网页版

    立刻MV 面向音乐人、内容创作者和品牌团队,帮助用户低成本完成歌曲 MV、歌词视频、AI 分镜、图生视频与最终合成。

    蛙蛙写作 网页版
    蛙蛙写作 网页版

    蛙蛙写作 AI 创作工具,覆盖小说、剧本、文案,一键生成文稿,打通文字转视频全流程,高效解决创作难题。

    讯飞智作 网页版
    讯飞智作 网页版

    讯飞智作是一款基于语音合成技术、虚拟人驱动技术与数字人形象声音构建能力的 AI 数字人音视频创作平台。

    超级简历WonderCV 网页版
    超级简历WonderCV 网页版

    超级简历WonderCV是面向应届生和AI小白的智能求职平台,覆盖简历、面试与职业规划。

    音述AI 网页版
    音述AI 网页版

    音述AI,是一个以“用声音述说故事”为核心的 AI 音乐创作与声音分享社区。

    AionClaw Windows版
    AionClaw Windows版

    AionClaw 是可在桌面端运行的任务型 AI 助手,通过数字专家与技能市场组合办公、创作、数据和开发能力。

    Loomy Windows版
    Loomy Windows版

    Loomy 是科大讯飞推出的桌面 AI 助手,可通过对话、任务与工作目录协助处理办公、内容创作和资料整理。

    AirServer Windows版
    AirServer Windows版

    AirServer Windows版可把电脑变成AirPlay、Google Cast和Miracast无线投屏接收端,适合会议演示、课堂教学及家庭大屏分享。发送设备通常无需另装客户端,并可同时接收和智能排列多个镜像会话。

    网站备案号:苏ICP备2026018738号-1 联系邮箱:bd@zhengruan.com

    Copyright ©2018-2026