DDIA-数据分区

540 阅读3分钟

数据分区与数据复制

分区通常与复制结合使用,即每个分区在多个节点都存在副本。这意味着某条记录属于某个特定的分区,但同样的内容会保存在不同的节点上以提高系统容错性。

键值数据的分区

分区的目标是将数据和查询负载均匀的分布在所有节点上,如果分区不均匀则会出现某些分区节点比其他分区节点承担更多的数据量和查询负载,称为倾斜

避免倾斜最简单的方法是:将记录随机分配到所有节点。但这带来一个问题:当试图读取特定的数据时,没有办法知道数据保存在哪个节点上,不得不并行查询所有的节点。

为了解决随机读问题,现在我们假设所有数据是简单地键-值数据模型,这意味着我们可以类似查字典,通过键的首字母保存到对应的节点上,读取时根据首字母查字典,到特定节点读取数据。

基于关键字区间分区

一种分区方式是为每个分区提供一段连续的关键字或关键字区间范围,每个分区内可以按照关键字排序保存,这样可以轻松支持区间查询

每个分区的关键字的区间段不一定要均匀分布,因为数据本身可能就不均匀。例如 A 和 B 开头的单词数据量要比T、U、V 开头的单词数据量大得多。为了更均匀的将数据量分摊到所有分区节点上,需要考虑数据本身的分布情况。

基于关键字区间分区的缺点是某些访问模式会导致热点。例如一个保存网络传感器数据的系统,如果关键字是时间戳则分区对应一个时间范围,即每天一个分区。对于当天来讲,所有写请求都会集中到一个分区上,出现写倾斜。

为了避免写倾斜问题,我们可以细化关键字粒度,采用传感器名称+时间戳的方式,将写负载均匀的分不到不同的节点上。当需要读取一段时间范围内多个传感器的数据时,可以根据传入的传感器名称,分别地并行执行区间查询。

基于关键字哈希分区

对于上述的数据倾斜与热点问题,许多分布式系统采用基于关键字哈希函数的方式来分区,可以很好地处理数据倾斜。

用于数据分区的哈希函数并不需要很强的加密能力,例如 Cassandra 和 MongoDB 使用 MD5,许多编程语言也有内置的哈希函数,如 Java的Object#hashCode 和 Ruby的 Object#hash,但由于它们在处理:同一个键在不同的进程中可能返回不同的哈希值的原因,并不适合分区。

关键字哈希分区的方法可以使关键字均匀的分摊到不同的分区,分区边界可以是均匀间隔也可以是随机选择(在这种情况下,该技术有时被称为一致性哈希,吐槽脸好多名词...)。

关键字哈希分区的缺点是丧失了良好的区间查询特性。即使关键字相邻,但经过哈希后会分散在不同的分区中,区间查询就失去了原有的有序相邻的特性。