分区、复制和存储布局:分片键决定事务与查询的共置域
1 亿订单按 user_id 分 16 片,最大商家占 40% 请求——用户查询均摊了,商家报表跨 16 片,热点分片 8,000/秒独木难支。本页区分分区与复制的不同目的,给出在线搬迁协议与跨分片唯一性的隐含代价。权威边界的定义见所有权、身份与不变量;各存储引擎的分区/复制实现由数据存储主题权威讲授,本页只讲跨系统布局。
分区、复制与故障域是三个层次
分区是数据分割,副本是数据复制。分区通常提高总存储和并行处理能力;副本提高读取或故障恢复能力。增加副本不会自动提高单分区写入上限。逻辑分片、物理实例和部署故障域是不同层次:多个逻辑分区可在同一实例上,故障时一起不可用;跨区复制若共享管理控制面,仍可能共同失败。
选择分区边界时要平衡热点、事务跨区率、重新平衡成本和恢复速度。对尚未达到单库限制的系统,分片也可能增加连接、迁移和全局查询复杂度。
先算热点,再决定分片键
假设1亿订单按user_id分16片,最大商家占总请求40%。user_id分片可能均摊用户查询,却让商家报表跨16片;按merchant_id又使最大商家成为热点。分片键决定事务和查询的共置域,不能只看总数据除以分片数。
若总峰值2万/秒,最大键域占40%即8000/秒,即使其余片空闲,单片仍需承担这8000。拆一个热点域需引入子分片和聚合协议,范围查询、分页与唯一键也随之变化。全局ID保证不碰撞不等于跨分片业务唯一意图可被原子约束。
复制与布局的不同目的
分片扩展数据与负载容量,复制增加可用/读容量,两者都增加恢复和协调。三副本并不把单写主吞吐直接乘三;副本读存在滞后,读后写、权限和余额裁决要另选路径。布局还包括字段宽度、索引数量、冷热分层与保留期,降低写放大往往比盲目加片有效。
迁移500GiB有效数据,净迁移带宽50MiB/秒,理想需约2.84小时;若前台新增10MiB/秒共用此预算,实际追赶需按剩余40MiB/秒算约3.56小时,且索引重建、日志和热点页竞争会拉长。不能用网卡峰值代替可持续迁移带宽。
在线搬迁协议与反例
先建立目的副本/分片,快照带水位,持续增量,校验后切路由,保留旧读窗口。迁移时所有写必须有主权:双边无协调写会产生分叉。跨分片分页使用稳定排序与游标,避免简单拼接各分片offset造成重复/漏行。
验证不仅比总行数:按分片/租户核对业务键、版本、金额汇总、删除墓碑与增量水位。恢复实验应测最大分片,不用平均分片掩盖长尾。数据库索引与存储的实际代价由 MySQL 主题等权威讲授,本页模型输入需用目标存储实测校准。
跨分片唯一性和分页的隐含协议
假设业务要求同一 external_order_id 只入账一次,却按user_id分片。若相同外部单可能被错误地传入两个user_id,各片唯一键都可成功,全局业务约束仍被打破。可选按不可变业务身份路由、建立有明确原子性的意图登记、或让来源先分配受控归属。全局ID生成器解决ID碰撞,不会自动裁决同一外部意图是不是重复请求。
查询各片最新20条时,协调器至少需要按相同全序键合并候选,并给相同时间的记录稳定tie-breaker。跨页若数据继续写入,游标还应说明快照/水位或允许的并发变更语义;单纯保存每片OFFSET在搬迁和删除后容易漏读或重复。深分页、跨片聚合和跨片事务的需求可能反过来改变分片键,不只是实现细节。
恢复最大分片需6小时而业务RTO为1小时,增加正常读副本数不一定解决:共享故障域、损坏传播、备份可用性和重建带宽都需单独分析。可以缩小恢复单元、准备可晋升副本、提高受控恢复带宽或分级恢复,但每种方案都有写放大、存储与运维代价。验收必须用最大热点分片和恢复期间负载,而不是只恢复空表或平均大小样本。
分片并非越早越好。若当前压力来自无索引全表扫描或长事务,先分16片可能只是复制16份复杂度;先纠正访问模式、schema与容量证据,再判断单域何时越界。设计要写出触发拆分的资源阈值和迁移准备,避免把"暂不分片"误当永不演进。
上下文关系如何决定分片共置
本页前面讲"分片键决定事务与查询的共置域",但分片键不是从数据量算出来的,它由上下文关系决定。先画上下文映射,再谈分片,顺序反了就会把强一致调用拆到两个分片里。
六种上下文关系各有数据含义:合作关系(两个上下文同步演进、共享发布节奏)、客户-供应商(下游依赖上游的发布计划)、遵奉者(下游全盘接受上游模型)、防腐层(下游用转换层隔离上游模型变化)、共享内核(两个上下文共享一小块模型,改动必须同步)、发布语言(跨上下文只交换稳定契约)。关系越"紧密",共置需求越强。
把关系映射到共置决策:合作关系与共享内核通常要求同库或同分片,避免同步调用跨网络;客户-供应商可以跨分片,但要有明确的契约版本与发布窗口;遵奉者与防腐层最适合按聚合边界分片,因为下游已经隔离了上游变化;发布语言是唯一可以跨故障域的关系,代价是契约演进与投影延迟。
以一个订单系统为例:结算上下文与订单上下文共享金额与状态(共享内核),必须同分片;通知上下文通过集成事件消费(发布语言),可以独立分片;报表上下文用防腐层读投影,分片自由但接受陈旧。若把共享内核的一段拆到另一个分片,每次金额裁决都要跨分片 RPC,本地事务变成分布式协调——这正是本页开头"拆库改变业务保证"的具体形态。
执行 python3 labs/context_model.py context_boundaries:模型枚举上下文之间的边,只允许 ID 引用与集成事件;把"报表直接读订单表"与"联表查询"标为违规。预期输出 violations 两条(DIRECT_TABLE、JOIN)、allowed 三条,并演示旁路读到未发布版本(bypass_sees_version=2 而 published_versions=[1])。脚本只检查规则,不证明真实分片性能。
两个合理选择:A 按团队边界分片,沟通成本低,但可能把共享内核拆开、制造跨分片强事务;B 按上下文关系分片,边界与一致性一致,但团队需要跨域协作。本例选 B,并把"共享内核清单"作为分片方案的前置交付物——清单上没有的字段,不允许出现在跨分片同步调用里。
架构师变化条件
把最大商家从"一个键域"升级为"需要子分片":子分片键、聚合协议与跨子片唯一性要重新定义,报表从 16 片 fan-out 变为 16×N。把 RTO 从 6 小时收紧到 1 小时:恢复单元必须缩小或引入可晋升副本,写放大与存储成本进入容量预算(见容量推导与故障余量)。若租户要求物理隔离,分片域与租户域重合,迁移与配额策略随之改变(见租户隔离与数据生命周期)。每次变化重算热点、事务跨区率与恢复窗口。
闭卷验收
本页 8 道闭卷题收进了下方自测面板:先回忆,再展开参考答案与评分点,最后给三档自评。