分布式系统数据分区

·  阅读 46

数据复制是通过冗余副本的方式,提高数据的高可用,数据复制考虑的是从节点的状态要跟上主节点,以及多主节点之间的数据冲突问题。但是数据复制始终受限于单节点的容量问题,比如一个节点最多能放PB、TB级的数据量,但它总有一个上限。

所以数据分区把数据切分成不同的区间,分别放在不同的节点,只要分区节点足够多,就能容纳足够多的数据。在数据分区时,我们是希望各个分区的数据能均衡分布,而不是某些分区节点成为热点而造成压力。

数据分区有几个方面需要关注:

(1) 如何把数据切分;

(2) 切分后,对于分区节点的伸缩,数据又如何再平衡

(3) 数据如何路由到目标分区节点

一、如何分区

1、基于区间分区

{

    "name": "Tom",\


    “favorite": “reading"

}

{

    "name": “Alex",

    “favorite": “dancing"

}
复制代码

考虑以上文档,我们对关键字name进行分区,假如把首字母A-F放到分区1,H-N放到分区2,以此类推,把剩余的区间划分到其他分区。

这种分区简单,且对分区内,还能进行范围查询,但是也很容易造成数据分布不均衡,比如大部分数据落在A-F的分区1,且其他分区只有一小部分数据。

2、基于哈希分区

假设分区1的哈希值范围[0,10000],分区2的哈希值范围是[10001, 20000],以此类推,根据某一哈希函数得到:

hash(“Tom”) = 10210, hash(“Alex”) = 98

基于哈希函数分区,可以得到较为均衡的分布,但是在分区内无法进行范围查询。

3、复合分区

复合分区其实是区间分区和哈希分区的一种折中,使用多个列组成复合键,复合键的一部分用来哈希分区,其他部分用来范围查询。

二、分区再平衡

我们一般不会使用取模的方式来划分分区,因为在增加分区节点时,会频繁地有数据从一个分区转移到另外一个分区,比如原来的 %10 和增加一个分区节点后的 %11,结果很不一样,就需要迁移。

我们的目标就是为了在增加分区节点时,尽量减少迁移。有两种措施:1是采用固定数量的分区,2是动态分区。

1、固定数量的分区

首先创建远超节点数的分区数,为每个节点分配多个分区,如果集群增加节点,那么就可以从现有的每个节点分走几个分区,这样直到数据再次均衡。

这个过程会有数据从部分节点迁移到新的节点,但是总体上,分区数是不会变的,因为分区数是我们在分区之前对系统未来发展最大限度的一个预估,足以支撑数据容量。但是这个预估有点难度,分区数多了和少了,都会造成不必要的开销,很难预估到合适的数量。

2、动态分区

动态分区也是每个节点承载多个分区,但是分区的数量是由数据量动态划分的,动态分区还会把一个大的分区拆开变成多个分区,也可能会把小的分区合并成一个分区。

动态分区的分区到节点的映射,可以由手工执行,也可以软件自动执行,或者二者结合起来。

三、数据路由

我们现在考虑的是,如何能把数据路由到对应的?

1、由客户端请求某个节点,如果数据在该节点,就由该节点返回,如果不存在,那就把请求转发到其他节点,最终返回给客户端。

2、客户端请求路由节点,由路由节点转发到对应的分区节点,路由节点不处理业务逻辑。

3、客户端持有分区-节点的映射关系,由客户端直接访问节点。

但是还有一个问题是,分区和节点的映射关系,如何维护,我们要知道,分区和节点都是会变化的,所以,这种关系是要时刻维护,并把更新通知到上述的参与者。

一种方案是由独立的协调服务维护,比如可以存放在Zookeeper,所有节点注册到Zookeeper,由Zookeeper的通知机制,完成这种变化的通知。

分类:
后端
收藏成功!
已添加到「」, 点击更改