单机库撑到瓶颈时,你会遇到几个具体问题:数据放一台机器存不下、写入全靠一个主库、跨机房查询慢得离谱。这时候要上的就是分布式数据库,但它的特点和设计方法和单机库完全不是一回事,照搬会踩坑。这篇给一套判断标准和可执行动作:先分清它到底解决了什么,再看常见的设计方法各自适用什么场景,最后给一份排查顺序。
单机库撑到瓶颈时,遇到的问题通常很具体:数据放一台机器存不下、写入全压在一个主库、跨机房查询慢到业务等不起。这时候才轮到分布式数据库上场。但它和单机库在特点与设计方法上完全不是一回事,把单机那套思路直接搬过来,多半会在分片、复制、一致性这三件事上踩坑。
这篇不讲概念堆砌,给的是判断标准和可执行动作。先分清分布式数据库到底改变了什么,再看常见设计方法各自适用什么场景,然后在分片键这种最容易翻车的地方给出选法,最后补一份落地前的排查顺序。全程不给死数字,涉及规模、延迟、价格的对比,到站内页面按当时的数据核对。
分布式数据库的核心特点:它到底改变了什么
最本质的变化只有一句:把「一台机器扛所有」换成「多台机器分工」。听起来是加法,实际代价在三处变贵——节点之间要走网络调用、多副本之间要协调数据一致性、节点数量一多运维复杂度就上台阶。所以判断要不要上,先看你现在的瓶颈到底在哪。
- 分片透明
- 业务代码不用关心数据落在哪个节点,路由由中间层解决,但路由规则的错误会以「查不到数据」的形式暴露出来
- 副本冗余
- 同一份数据存多份,坏一台不影响读,代价是写入要等副本确认,延迟随副本数上升
- 分布式事务
- 跨节点的写操作要保持原子性,实现难度和延迟都明显高于单机事务,能不用就别用
- 全局时钟或一致性协议
- 用来给跨节点操作定序,是很多分布式能力的地基,也是故障排查时最先要看的组件
- 在线扩缩容
- 加节点时数据要迁移、分片要重分布,这是持续能力,不是一次性动作
- 瓶颈是单机存储不够、候选集太大:分片存储和并行扫描能帮上忙
- 瓶颈是写入吞吐打满主库:多分片并行写有用,但要先确认业务能否接受最终一致
- 瓶颈是单条查询或单条事务太慢:先查索引和执行计划,换架构大概率无效
- 瓶颈只是读多写少:先考虑读副本和缓存,成本比改架构低得多
- 用不上的特性别开:每多一个组件,故障面就多一块
常见设计方法:分片、复制、一致性怎么搭
设计方法可以拆成三条独立决策:数据怎么分、副本怎么放、一致性取到什么程度。三条要分开讨论、再合起来验证,混在一起谈很容易做出一个说不清取舍的方案。下面这张表是常用的对照关系。
| 决策 | 常见做法 | 适合什么场景 | 什么情况下不适用 |
|---|---|---|---|
| 分片 | 按主键哈希 | 写入分布均匀、点查为主 | 范围扫描和区间统计多的业务 |
| 分片 | 按范围切分 | 时间区间查询、批量归档 | 写入集中在最新区间的业务,容易热点 |
| 分片 | 按业务维度(租户、地区) | 需要按客户隔离、便于独立扩容 | 存在超大租户或地区流量严重不均 |
| 复制 | 一主多从、读写分离 | 读多写少,实现和排查都最简单 | 主库写吞吐本身就是瓶颈时 |
| 复制 | 多副本可写 | 要求高可用、不能有单点写入 | 冲突解决规则说不清的写入场景 |
| 一致性 | 强一致 | 涉及余额、库存扣减等不能出错的写 | 对延迟敏感的大批量写入路径 |
| 一致性 | 最终一致 | 统计、推荐、派生数据 | 用户刚提交就要立刻看到结果的页面 |
一个务实的混合做法是:核心交易表走强一致,派生出来的统计、报表、搜索索引走异步同步。这样既守住正确性,又不让整条链路被最慢的一致性要求拖住。具体到产品能力差异,到 /price-watch 看当时的对比再定,不要凭印象选。
分片键与数据分布:最容易翻车的一步
分片键是整套架构里最难改的东西。扩容时再想换键,往往要停机导数据,所以选键之前先把高频查询的过滤条件列全,让分片键能命中大部分查询,至少别让绝大多数请求都变成跨分片查询。
- 列查询清单把线上高频查询按调用量排序,标出每条查询的过滤字段,找出出现次数最多的那一组
- 选候选键从高频过滤字段里挑分布均匀、且能覆盖多数查询的字段作为候选分片键
- 验分布用真实或近似真实的数据做一次分布模拟,看各分片的行数和写入量是否接近;偏差大的键直接淘汰
- 测热点单调递增的键(时间、自增 ID)会把写入压到单个分片,验证方式是看单位时间内各分片写入是否均衡
- 定跨分片策略把必须跨分片的查询和事务单独列出来,能靠冗余字段规避的聚合尽量规避,剩下的才走分布式事务
防热点比防倾斜更优先。倾斜只是资源浪费,热点会直接把一个分片打挂。常用缓解手段是给单调键加随机后缀,或者按时间预分桶,把写入摊到多个分片上。代价是范围查询会变复杂,这一点要在设计文档里写清楚。
代价与不适用场景:什么时候别上分布式
分布式不是免费的升级,它把复杂度从数据库内部搬到了架构和业务代码里。判断标准很简单:如果单机库加索引、加读写分离、加缓存还能撑住,那先做这三件事,因为它们的收益确定、回退也容易。
- 数据量和并发都还小的时候:提前上分布式,换来的是没有收益的复杂度
- 强事务密集、且数据量可控的场景:单机或主从方案的行为更可预测
- 团队没有对应运维能力的时候:扩缩容、数据重分布、一致性排查都需要专人盯
- 迁移窗口极短、又没人能长期跟进的时候:先补能力,再谈架构替换
- 只有当容量或写入吞吐确实成为硬瓶颈、且业务能接受相应一致性取舍时,才值得上
分布式数据库解决的是规模和吞吐问题,不是性能问题;指望它让单条查询变快,方向从一开始就错了。
落地前的排查顺序与验证清单
按固定顺序推进,比东一榔头西一棒子省时间得多。顺序错了最典型的后果是:产品都选完了才发现分片键覆盖不了核心查询,只能回头重做。
- 先量现状统计当前数据量、写入与查询的峰值、慢查询的分布,形成一份基线,后面所有对比都对着它
- 定分片键与一致性要求按上一节的方法选键,同时把每类数据的一致性等级写进设计文档,明确哪些能最终一致
- 选具体产品拿自己的分片键和一致性要求去套产品能力,看哪家的路由、副本、事务模型真的匹配;各家当前能力与价格到 /sites 核对当时的资料
- 做容量与热点压测用接近真实分布的数据压测,重点看单分片是否先到瓶颈,结果和基线放在一起对比
- 定迁移与回退方案先双写或增量同步,再灰度切读,每一步都要有能退回单机的路径
- 补可观测性上线前把分片级监控、跨分片查询次数、复制延迟、重试率四项接上,缺哪项先补哪项
常见问题
分布式数据库和单机数据库最本质的区别是什么?
区别不在于「多台机器」,而在于数据是否被切开存放、请求是否被分发到不同节点处理。这带来两个直接后果:跨节点的操作需要额外的一致性协调,出问题的排查路径也从一条 SQL 变成「哪台机器、哪个分片、哪次复制」。如果数据量和并发没到单机撑不住的程度,这些成本换不来收益。
分片键该怎么选,有没有通用的判断顺序?
没有万能键,但有顺序:先列出线上最高频的几条查询和它们的过滤条件,挑能命中最多查询的字段作为候选;再看该字段的取值分布是否均匀,单调递增的字段要加扰动;最后确认它是否会被业务改动,会变的字段不适合做分片键。选完要做一轮热点压测再定,别只在文档上论证。
已经上线了想换分片键,还有救吗?
有救但代价不小,通常做法是双写加渐进迁移:新老分片规则并行一段时间,用后台任务把历史数据搬到新分布,读路径先切、写路径后切,期间靠对账校验一致性。这个过程要评估停机窗口和数据量,具体能省多少时间取决于数据规模,拿不准就先在测试环境跑一遍完整迁移演练。