数据分片
解释数据量或吞吐超过单节点容量后如何按分片键水平拆分数据,以及路由、热点、重平衡和跨分片操作为何成为新的系统成本。
[!info] related notes
- 所属 MOC:Distributed Systems MOC
- 前置:分布式系统
- 相邻:数据复制、分布式事务
- 组件映射:Kafka Partition、Elasticsearch Shard、Redis Cluster
数据分片
[!abstract] 一句话定义 Sharding 按 Shard Key 将不同数据水平分布到多个节点,以突破单节点容量和吞吐上限。它把一个大数据集拆开,同时引入数据路由、热点、再平衡、跨分片查询和跨分片事务。
基本模型
shard = route(shard_key)
user_id 1..N
→ Shard A / B / C / D
应用、Proxy 或数据库路由层必须能从请求中确定目标 Shard;无法定位时就需要 Scatter-Gather。
三种常见分片方式
Hash Sharding
hash(user_id) mod N
分布通常较均匀,但扩容时直接改变 N 会导致大量 Key 迁移。可使用一致性哈希、虚拟节点或固定 Slot 降低迁移范围。
Range Sharding
A-F → Shard 1
G-M → Shard 2
N-Z → Shard 3
范围查询自然,但递增 ID、热点时间段或大客户可能形成热点 Shard。
Directory / Lookup Sharding
维护 entity → shard 映射,迁移灵活,但路由表成为额外依赖和一致性边界。
Shard Key 是核心设计
好的 Shard Key 通常需要:
- 高基数、分布相对均匀;
- 大部分请求都能提供;
- 与主要查询/写入边界一致;
- 同一事务所需数据尽量共置;
- 不易频繁变化;
- 支持未来扩容与迁移。
[!warning] 均匀不等于合适 随机 UUID 可能分布很好,但如果所有业务查询都按
tenant_id,每次都需要扫全部 Shard,系统仍然很差。
四类新问题
1. Hot Shard
某个 Tenant、时间段、Key 或 Partition 承担过多流量。治理:复合 Key、分桶、拆热点实体、流量隔离或专用 Shard。
2. Rebalancing
新增节点时需要迁移数据:
copy data
→ catch up incremental writes
→ switch routing
→ verify
→ remove old copy
过程需要版本、双写/日志追赶、限速、回滚和观测。
3. Cross-shard Query
聚合、排序、分页和 Join 需要向多个 Shard 发请求并合并结果。Deep Pagination 和全局 Top-K 成本会显著提高。
4. Cross-shard Transaction
跨 Shard 更新无法直接依赖单节点本地事务,可能需要 2PC、Saga、Outbox、重构 Aggregate 或接受最终一致。
Replication 与 Sharding
Sharding
→ split different data for capacity
Replication
→ copy same data for availability
常见拓扑:每个 Shard 再有 Leader + Replicas。于是路由、复制、选主和再平衡同时存在。
扩容不是免费线性增长
增加 Shard 可能提升并行度,也会增加:
- Connection 数;
- Metadata;
- Small Shard Overhead;
- Scatter-Gather;
- Rebalance;
- Failure Domain;
- 运维和 Backup 复杂度。
先确认瓶颈真的是单节点容量,而不是缺索引、慢查询或错误缓存策略。
观测重点
per-shard size / QPS / latency
key and tenant distribution
hot partition rate
cross-shard query fanout
rebalance progress / migration errors
replication lag per shard
connection and metadata overhead
设计检查表
- Shard Key 同时考虑分布与查询局部性。
- 热点 Tenant / Key 有独立处理策略。
- 路由表和版本可审计、可回滚。
- 跨 Shard Query / Transaction 有明确成本和替代方案。
- Rebalance 支持增量追赶、限速、验证和失败恢复。
- Backup / Restore 能按 Shard 和全局时间点协调。
- 先优化单节点和 Schema,再决定 Sharding。