Skip to content

关系型与非关系型数据库 ​

Category ​

database / 存储选型。节点定位:不问「关系型还是 NoSQL」,按失败代价与访问模式给数据分层配存储——混合是常态,难的是每层职责说得清。

Definition ​

讨论数据库选型时,最容易犯的错就是问“到底该用关系型还是 NoSQL”。这个问题本身就太粗。更实际的问法应该是:这份数据需要什么一致性、怎样被查询、如何迁移和恢复、能不能接受模式演进成本。只有把这些问题答清楚,关系型和非关系型才有工程意义。

现实里,大多数成熟项目都不会只用一种存储。真正要做的是承认不同数据有不同要求,而不是追求一种存储模型统治全场。

Problem ​

「关系型还是 NoSQL」这个问题太粗,粗到选型会变成产品宗教之争。真正要先答的是:这份数据写错一次的代价是什么、需要什么一致性、怎么被查询、未来要不要迁移。答案不同,存储不同——大多数成熟项目最后都是混合存储,难的不是选哪个,而是谁是源数据、谁是副本、谁负责重建说得清。

关系型数据库真正擅长什么 ​

关系型数据库最值钱的地方,通常在于:

  • 事务和约束能力较强
  • 数据结构清楚,语义更稳定
  • 对长期资产和审计链路更友好
  • 复杂查询和多表关系表达能力更成熟

所以角色资产、订单、交易、任务进度、发奖记录这类需要清晰边界和较强一致性的状态,往往更适合由关系型数据库承接。

非关系型存储真正擅长什么 ​

非关系型不是“更先进的数据库”,而是更适合某些访问模式:

  • 主键直取和高吞吐 KV 访问
  • 模式灵活的数据结构
  • 大规模日志与文档存储
  • 特定场景下更容易水平扩展

它更像是在优化某类问题,而不是自动替代关系型数据库。如果业务真正依赖严格事务、强约束和长期可审计性,光靠“更灵活”通常不够。

为什么很多项目最后会混合使用 ​

因为一套游戏系统里通常同时存在这些需求:

  • 资产链路要求强一致和可追责
  • 在线链路要求低延迟和高吞吐
  • 查询侧要求聚合和多维检索
  • 历史侧要求低成本归档和离线分析

关系型、KV、缓存、搜索和数仓分别擅长不同部分。真正重要的不是是否混用,而是每一层的职责有没有被说清楚。

选型时最该先看的不是产品,而是失败代价 ​

更实用的判断方式通常是:

  • 这份数据写错一次的代价是什么
  • 读取延迟可容忍到什么程度
  • 是否需要复杂查询或事务约束
  • 未来是否一定会迁移、合服或归档

例如排行缓存短时滞后和玩家资产错误,代价完全不同。前者可以接受派生副本和最终一致,后者通常必须围绕权威存储来设计。

模式灵活不等于演进成本低 ​

很多团队偏爱非关系型,是因为前期看起来模式更灵活、迭代更快。但真正进入长线运营后,模式不受约束也会带来新的成本:

  • 字段语义漂移
  • 历史数据结构不一致
  • 回填和迁移脚本越来越复杂
  • 查询逻辑不断堆积补丁

所以模式灵活能帮你跑得更快,但如果没有额外治理,它也会让后面更难收口。

一个更稳妥的选型思路 ​

比较稳妥的做法通常是:

  • 把长期资产和高价值状态优先放在更强约束、更易审计的存储上
  • 把高吞吐、低价值、单一访问模式的数据放到更轻量的模型里
  • 把搜索、排行、报表这类查询优化结构明确当作派生副本
  • 提前考虑未来迁移和模式演进,而不是只看当前开发速度

这个思路的关键不是保守,而是承认存储选型本质上是在选择未来要承担哪种维护成本。

常见误区 ​

最常见的错误,是把数据库选型做成产品宗教之争,而不是按数据性质和失败代价做判断。第二类错误,是为了前期灵活,把长期资产也塞进缺少约束的存储模型里。第三类错误,是混用了多种存储,却没有明确谁是源数据、谁是副本、谁负责重建,最后整套系统失去可解释性。

Used By ​

存储选型评审(按数据性质与失败代价分层,而不是按产品名单);混合存储体系里给每一层登记职责(源/副本/重建路径);模式演进与迁移成本评估。

  • KBEngine(commit 0bc93d5):选型沉到实现层而不是架构层——DBInterface 是一组纯虚(kbe/src/lib/db_interface/db_interface.h:53、:80),底下并排两个实现:DBInterfaceMysql : public DBInterface(kbe/src/lib/db_mysql/db_interface_mysql.h:58)与 DBInterfaceRedis : public DBInterface(kbe/src/lib/db_redis/db_interface_redis.h:32)。同一份实体数据落到关系型还是内存型,是配置与实现选择,不是架构分歧

关系链:状态分类(01)→ 失败代价定价 → 存储分层 → 源/副本语义 → 演进与迁移预留。下游:事务与一致性(03,资产层怎么保正确)、cache 子树(读加速层的定位与锁)。

Reference ​

本页为工程经验归纳,无单一外部出处。

游戏知识体系