跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像AI 生图工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++

C++ 微服务中的 RocksDB 存储层设计

C++ 微服务架构下 RocksDB 存储层的设计实践,包括 Store 接口抽象、Key 规范、WriteBatch 原子操作、前缀查询及 JSON 序列化。通过独立实例路径规划与接口隔离实现高可用与可扩展性,支持多存储介质替换。

GitMaster发布于 2026/3/15更新于 2026/7/2042 浏览
C++ 微服务中的 RocksDB 存储层设计

C++ 微服务中的 RocksDB 存储层设计

  • 项目仓库:https://github.com/YW8862/SwiftChatSystem

一、Store 接口抽象概览

SwiftChatSystem 中,业务逻辑通过 Store 接口 访问持久化数据,具体实现可替换(RocksDB、MySQL、Redis 等),业务层无需改动:

RocksDB 实现

存储抽象

业务层

Handler

Service

UserStore

SessionStore

FriendStore

MessageStore

GroupStore

FileStore

RocksDB

服务Store职责
AuthSvrUserStore用户数据、username→user_id 索引
OnlineSvrSessionStore登录会话、token
FriendSvrFriendStore好友关系、好友请求、分组、黑名单
ChatSvrMessageStore、ConversationStore、ConversationRegistry消息、会话列表、私聊会话元信息
ChatSvrGroupStore群组、群成员、用户群列表
FileSvrFileStore文件元信息、md5 索引、上传会话

二、Key 设计规范

2.1 通用格式
{类型}:{主键}:{可选子键} 

类型前缀用于区分不同业务数据,便于迭代与排查;主键与子键组合形成唯一 Key。

2.2 全量 Key 汇总
前缀格式示例Value用途
user:user:u_123UserData JSON用户主数据
username:username:aliceuser_id登录时按用户名查
session:session:u_123SessionData JSON登录会话(OnlineSvr)
friend:friend:u_1:u_2FriendData JSON好友关系
friend_req:friend_req:req_xxxFriendRequestData JSON好友请求
friend_req_to:friend_req_to:u_2:req_xxx''收到的请求索引
friend_req_from:friend_req_from:u_1:req_xxx''发出的请求索引
friend_group:friend_group:u_1:defaultFriendGroupData JSON好友分组
block:block:u_1:u_3'1'黑名单
msg:msg:m_789MessageData JSON消息正文
chat:chat:c_123:rev_ts:m_789''会话时间线索引
conv:conv:u_1:c_123ConversationData JSON用户会话列表
conv_meta:conv_meta:p_u1_u2{"type":"private"}私聊会话元信息
offline:offline:u_123:rev_ts:m_789''离线消息索引
group:group:g_xxxGroupData JSON群元数据
group_member:group_member:g_xxx:u_1GroupMemberData JSON群成员
user_groups:user_groups:u_1:g_xxx''用户群列表索引
file:file:abc123FileMetaData JSON文件元信息
file_md5:file_md5:d41d8cd98ffile_id秒传索引
upload:upload:xyz789UploadSessionData JSON上传会话

三、WriteBatch 原子写入

当一次操作需要写入或删除多条记录时,使用 rocksdb::WriteBatch 保证原子性:要么全部成功,要么全部失败,避免中途崩溃导致数据不一致。

3.1 示例:UserStore.Create

注册需同时写入 user:{id} 与 username:{name},缺一不可:

bool RocksDBUserStore::Create(const UserData& user) {
    rocksdb::WriteBatch batch;
    batch.Put("user:" + user.user_id, SerializeUser(user));
    batch.Put("username:" + user.username, user.user_id);
    rocksdb::WriteOptions wo;
    wo.sync = true;
    return impl_->db->Write(wo, &batch).ok();
}
3.2 示例:FriendStore.AddFriend

好友关系为双向,需同时写入 A→B 与 B→A:

bool RocksDBFriendStore::AddFriend(const FriendData& data) {
    rocksdb::WriteBatch batch;
    batch.Put(KeyFriend(data.user_id, data.friend_id), SerializeFriend(data));
    batch.Put(KeyFriend(data.friend_id, data.user_id), SerializeFriend(reverse));
    rocksdb::WriteOptions wo;
    wo.sync = true;
    return impl_->db->Write(wo, &batch).ok();
}
3.3 示例:MessageStore.Save

一条消息需写入消息本体与会话时间线索引:

bool RocksDBMessageStore::Save(const MessageData& msg) {
    rocksdb::WriteBatch batch;
    batch.Put(KeyMsg(msg.msg_id), SerializeMessage(msg));
    batch.Put(KeyChat(conversation_id, msg.timestamp, msg.msg_id), "");
    rocksdb::WriteOptions wo;
    wo.sync = true;
    return impl_->db->Write(wo, &batch).ok();
}
3.4 示例:GroupStore.RemoveMember

踢人需同步更新 group_member、user_groups、group 的 member_count:

rocksdb::WriteBatch batch;
batch.Delete(KeyGroupMember(group_id, user_id));
batch.Delete(KeyUserGroup(user_id, group_id));
batch.Put(KeyGroup(group_id), SerializeGroup(*g)); // 更新 member_count
return impl_->db->Write(wo, &batch).ok();

四、迭代器与前缀查询

RocksDB 的 key 按字典序排列,通过 Seek(prefix) + 迭代可高效实现「按前缀扫描」。

4.1 典型模式
std::string prefix = "friend:u_123:"; // 例如好友列表
rocksdb::Slice prefix_slice(prefix);
std::unique_ptr<rocksdb::Iterator> it(impl_->db->NewIterator(rocksdb::ReadOptions()));
for (it->Seek(prefix); it->Valid(); it->Next()) {
    if (!it->key().starts_with(prefix_slice)) break; // 处理 it->key() 和 it->value()
}
4.2 应用场景
Store前缀用途
FriendStorefriend:{user_id}:获取用户好友列表
FriendStorefriend_req_to:{user_id}:获取收到的好友请求
FriendStorefriend_group:{user_id}:获取好友分组
FriendStoreblock:{user_id}:获取黑名单
MessageStorechat:{conversation_id}:获取会话历史(配合 rev_ts 倒序)
MessageStoreoffline:{user_id}:拉取离线消息
ConversationStoreconv:{user_id}:获取用户会话列表
GroupStoregroup_member:{group_id}:获取群成员
GroupStoreuser_groups:{user_id}:获取用户加入的群
4.3 rev_ts 倒序设计

会话时间线与离线队列需「最新在前」分页。RocksDB 键按字典序升序,直接存 timestamp 则旧消息在前。采用 rev_ts = MAX_TS - timestamp(固定 13 位补齐):

chat:p_u1_u2:9999987654321:m_001 → 最新消息
chat:p_u1_u2:9999987654320:m_002 → 次新
chat:p_u1_u2:9999987654319:m_003 → 更早

迭代时 Seek(prefix) 即从最新开始,顺序读取即可实现倒序分页。


五、JSON 序列化与反序列化

各 Store 使用 nlohmann::json 将结构体与 JSON 互转,Value 存 JSON 字符串。

5.1 序列化示例
std::string SerializeUser(const UserData& user) {
    json j;
    j["user_id"] = user.user_id;
    j["username"] = user.username;
    j["password_hash"] = user.password_hash;
    j["nickname"] = user.nickname;
    // ...
    return j.dump();
}
5.2 反序列化示例
UserData DeserializeUser(const std::string& data) {
    json j = json::parse(data);
    UserData user;
    user.user_id = j.value("user_id", "");
    user.username = j.value("username", "");
    user.password_hash = j.value("password_hash", "");
    // ...
    return user;
}

j.value("key", default) 可在字段缺失时使用默认值,提高兼容性。

5.3 特殊处理
  • 数组:j["mentions"] 为 array 时需遍历 j["mentions"] 逐项 get<std::string>()
  • 数字:j.value("created_at", static_cast<int64_t>(0)) 避免类型问题
  • 可选字段:j.contains("md5") 判断后再读取

六、RocksDB 配置

6.1 通用 Options
rocksdb::Options options;
options.create_if_missing = true;
options.IncreaseParallelism();
options.OptimizeLevelStyleCompaction();
rocksdb::Status status = rocksdb::DB::Open(options, db_path, &db);
  • create_if_missing = true:路径不存在时自动创建
  • IncreaseParallelism():利用多核加速
  • OptimizeLevelStyleCompaction():优化 compaction 性能
6.2 WriteOptions
rocksdb::WriteOptions wo;
wo.sync = true; // 落盘后才返回,保证持久化
impl_->db->Write(wo, &batch);

生产环境通常使用 sync = true,避免进程崩溃导致 WAL 未落盘而丢数据。


七、多 DB 与路径规划

各服务使用独立的 RocksDB 实例,路径分离:

服务路径示例说明
AuthSvr/data/auth单库
OnlineSvr/data/online单库
FriendSvr/data/friend单库
ChatSvr/data/chat/message、/data/chat/conv、/data/chat/conv_meta、/data/chat/group多库
FileSvr/data/file-meta单库

ChatSvr 将 message、conv、conv_meta、group 分库,降低单库体积,便于备份与迁移。


八、扩展与替换

8.1 接口抽象的价值

业务层依赖 UserStore、FriendStore 等接口,而非 RocksDBUserStore。若需接入 MySQL:

class MySQLUserStore : public UserStore {
    bool Create(const UserData& user) override {
        /* SQL INSERT */
    }
    std::optional<UserData> GetById(const std::string& user_id) override {
        /* SELECT */
        // ...
    };
};

只需在 main 中替换 store = std::make_shared<MySQLUserStore>(...),Service 与 Handler 无需改动。

8.2 Key 命名的可移植性

当前 Key 设计为 RocksDB/Redis 等 KV 存储优化。若迁移到 MySQL,可将 user:u_123 映射为表 user 主键 u_123,username:alice 映射为唯一索引;语义保持一致,迁移成本可控。


九、小结

SwiftChatSystem 的 RocksDB 存储层设计可归纳为:

  1. Store 接口抽象:Handler → Service → Store,实现可替换
  2. Key 规范:{类型}:{主键}:{子键},类型前缀统一、便于迭代
  3. WriteBatch:多 Key 写入/删除用 WriteBatch 保证原子性
  4. 迭代器与前缀:Seek(prefix) + 迭代实现前缀查询;rev_ts 倒序支持「最新优先」分页
  5. JSON 序列化:nlohmann::json 统一 Value 格式,便于调试与兼容
  6. 配置与路径:create_if_missing、sync、多 DB 路径规划
  7. 可扩展性:接口抽象支持替换为 MySQL、Redis 等存储

目录

  1. C++ 微服务中的 RocksDB 存储层设计
  2. 一、Store 接口抽象概览
  3. 二、Key 设计规范
  4. 2.1 通用格式
  5. 2.2 全量 Key 汇总
  6. 三、WriteBatch 原子写入
  7. 3.1 示例:UserStore.Create
  8. 3.2 示例:FriendStore.AddFriend
  9. 3.3 示例:MessageStore.Save
  10. 3.4 示例:GroupStore.RemoveMember
  11. 四、迭代器与前缀查询
  12. 4.1 典型模式
  13. 4.2 应用场景
  14. 4.3 rev_ts 倒序设计
  15. 五、JSON 序列化与反序列化
  16. 5.1 序列化示例
  17. 5.2 反序列化示例
  18. 5.3 特殊处理
  19. 六、RocksDB 配置
  20. 6.1 通用 Options
  21. 6.2 WriteOptions
  22. 七、多 DB 与路径规划
  23. 八、扩展与替换
  24. 8.1 接口抽象的价值
  25. 8.2 Key 命名的可移植性
  26. 九、小结
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • Java 核心基础:语言特点、环境架构与八种基本数据类型详解
  • jQuery 核心实战:选择器、DOM 操作与表单验证详解
  • GitHub Copilot 登录失败常见原因与排查指南
  • C 语言算法与数据结构实战:从数组到递归的避坑之旅
  • C++ STL 常用容器详解与实战技巧
  • AI 长篇小说自动生成工具技术解析
  • Java 文件操作核心 API 与实战场景
  • Docker 存储卷深度剖析:从创建到实战,掌握容器数据持久化
  • 基于树莓派与 Sambert-Hifigan 的离线语音合成系统搭建
  • C++11 核心特性:列表初始化、新式声明与 STL 演进
  • Page-Agent: 一行 JS 代码实现大模型对前端 DOM 的精准操控
  • GitHub 学生开发者包认证全流程指南
  • 双延迟深度确定性策略梯度算法 (TD3) 详解与实现
  • Streamlit WebUI 实战:适配 Nanbeige、Qwen 与 Llama 大模型的方法
  • 宇树 G1 机器人 FAST-LIO 建图与 RViz 配置教程
  • JavaScript 精度丢失与金额分摊问题的工程化解决方案
  • 动态规划路径类 DP 入门:最小路径和、迷雾森林与过河卒
  • Flutter 集成 google_generative_language_api 适配鸿蒙 HarmonyOS
  • Qclaw 使用指南:微信集成 AI 智能体实践
  • StructBERT 中文相似度 WebUI 部署与故障排查指南

相关免费在线工具

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online

  • JSON 压缩

    通过删除不必要的空白来缩小和压缩JSON。 在线工具,JSON 压缩在线工具,online

  • JSON美化和格式化

    将JSON字符串修饰为友好的可读格式。 在线工具,JSON美化和格式化在线工具,online