本页目录
分片策略
数据怎么切成片,决定了查询的路由方式、负载的均匀程度、以及扩容时的迁移量。range 分片对范围查询友好但容易热点,hash 分片均匀但范围查询要扇出——没有银弹,只有针对访问模式的选择。
Range 分片
按 key 的字母/数字区间分配 shard。类似百科全书分卷:A-D → shard 1, E-H → shard 2, ...
优势:
- Range scan 高效: 查询
WHERE key BETWEEN 'a' AND 'c'只需访问一个 shard - 顺序写入连续: 最近的 key 放入同一个 shard → 顺序 IO
劣势:
- 热点: 如果某些 key 范围被频繁访问(如最近的 timestamp),该 shard 成为瓶颈
- 分布不均: 数据分布可能倾斜(某些字母范围的数据多)
应用:HBase, Bigtable, MongoDB range sharding。
Hash 分片
shard = hash(key) % N — 均匀分布到所有 shard。
优势:负载均衡,不产生热点(假设 key 分布均匀)。劣势:丢失 range scan — 连续的 key 被分散到所有 shard → range query 需要 scatter-gather 到所有 shard。
应用:Cassandra (Murmur3), DynamoDB (MD5)。Cassandra 的 partition key = hash(key),但支持 clustering columns 在同一 partition 内做 range scan。
Rebalancing
节点数变更时数据重新分配:
固定分片数: 创建时分配固定数量的分片(如 1000),每个节点承担多个分片。加节点 → 从现有节点迁移一些分片到新节点。优势:简单,平衡迁移成本均匀。劣势:分片数设定后难改(如果数据量增长远超 1000 个分片量)。
动态分片: 分片被允许分裂(当数据量超过阈值)和合并(当数据量低于阈值)。适应数据量增长,但有 split 期间的性能影响。
Hot Spot 缓解
某个 key 被极高频率访问 → 所在的 shard 成为瓶颈。缓解策略:
- Key salting:
key = original_key + random_salt→ 分散到不同 shard。读时从所有 salt variants 读并聚合。 - Caching: 热 key 在应用层缓存(Redis/Memcached)
- Partition-aware client: 客户端知道哪个 shard 有热 key → 直接连该 shard 而不是通过中间层 → 省一跳
Secondary Indexes on Sharded Data
Global secondary index (DynamoDB):
索引独立于主表分片 → 可以有自己的分片键
写: 主表写 + 异步更新索引(可能短暂不一致)
读: 索引直接指向目标 shard
Local secondary index (Cassandra):
索引与主表在同一个 partition 中
写: 原子(同一 partition 内,无需跨 partition 事务)
读: 必须指定 partition key → 只能扫描单个 partition
参考
- Cassandra: cassandra.apache.org/doc/stable/cassandra/architecture/dynamo.html
- DynamoDB: docs.aws.amazon.com/amazondynamodb/latest/developerguide/HowItWorks.Partitions.html
Keywords: range partitioning, hash partitioning, rebalancing, hot spot, key salting, secondary index, Cassandra, DynamoDB