本页目录

分片策略

数据怎么切成片,决定了查询的路由方式、负载的均匀程度、以及扩容时的迁移量。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