知识卡片
哈希分区用复合主键在负载均衡与范围查询间折衷
内容
[[键范围分区支持高效范围查询但按时间戳分区易造成写入热点]]的偏斜风险,可以通过对 键做哈希后再分区来规避:好的哈希函数能把即使很相似的输入也打散成均匀分布在整个 数值区间的”随机数”,为分区目的用的哈希函数不需要密码学级别的强度(Cassandra和 MongoDB用MD5,Voldemort用FNV函数),但要避免用编程语言内置的哈希函数,因为它们 可能在不同进程里对同一个键产生不同哈希值。哈希分区的代价是彻底打乱了键的顺序—— 原本相邻的键现在散落在各个分区,范围查询要么完全失效(Riak、Couchbase、Voldemort 不支持主键范围查询),要么要发给所有分区(MongoDB的哈希分区模式下范围查询必须 广播)。Cassandra给出了一个折衷:表可以用复合主键,只有第一列参与哈希决定分区, 其余列在分区内部按顺序存储、当作连接索引使用——这意味着如果查询锁定了第一列的 固定值,就能对后续列做高效的范围扫描,第一列决定”去哪个分区找”,其余列决定”分区 内怎么排序”。这个组合索引方法天然契合一对多关系:比如社交媒体更新用(user_id, update_timestamp)做主键,不同用户分散在不同分区实现负载均衡,同一用户的更新在 所在分区内按时间戳有序存储,能高效取出”某用户某时间段内的全部更新”,是哈希分区 和键范围分区两种思路结合的实用范例。
参考来源
- 位置:《数据密集型应用系统设计》第六章《分区》"根据键的散列分区"(源文件:
_epub-src/ch6_split_002.html)
- 结论依据:原文说明哈希分区靠MD5/FNV等函数均匀分布负载但丧失范围查询能力,
Cassandra用复合主键让第一列决定分区、其余列在分区内排序,并举社交媒体
(user_id, update_timestamp)主键的例子说明该组合方式如何兼顾负载均衡和范围
查询,直接支撑本卡片结论。
- 原始内容:一个好的散列函数可以将偏斜的数据均匀分布……不幸的是,通过使用键
散列进行分区,我们失去了键范围分区的一个很好的属性:高效执行范围查询的能力……
键中只有第一列会作为散列的依据,而其他列则被用作Casssandra的SSTables中排序
数据的连接索引……组合索引方法为一对多关系提供了一个优雅的数据模型。