《数据密集型应用系统设计》笔记六:第六章 数据分区

1. 数据分区方式

基于关键字区间分区

(1)为每个分区分配一段连续的关键字或关键字区间范围。
(2)关键字的区间段不一定要均匀分布,这主要是因为数据本身非常可能就不均匀。比如单词表,以x,i,o等开头的单词显然很少很少。为了均匀分布数据,分布边界应该适配数据本身的分布特征。
(3)基于关键字的区间分区的缺点是某些访问模式会导致热点。(比如关键字按天,节假日数据肯定会有明显不同)

基于关键字区间分区的问题:

(1)数据倾斜:如果分区不均匀,则会出现某些分区节点比其他分区承担更多的数据量或查询负载,称之为数据倾斜
(2)热点:数据倾斜会导致分区效率严重下降,极端情况下,所有的负载可能会集中在一个分区节点上,这种负载严重不成比例的分区即成为系统热点。

基于关键字哈希值分区

针对数据倾斜和热点问题,许多分布式系统采用了基于关键字哈希函数的方式来分区。

基于关键字哈希值分区,可以很好地将关键字均匀地分配到多个分区中。分区边界可以是均匀间隔。但是这种情况下可能并不能均匀分配负载,此时就需要一致性哈希。

基于关键字哈希值分区的缺点是:丧失了良好的区间查询特性。

基于哈希的分区可以减轻热点,但无法做到完全避免。一个极端情况是:所有的读/写操作都是针对同一个关键字,则最终所有请求都将被路由到同一个分区。(比如当年的鹿晗关晓彤事件)。大多数系统今天仍然无法自动消除这种高度倾斜的负载,而只能通过应用层来减轻倾斜程度。例如,如果某个关键字被确认为热点,一个简单的技术是在关键字的开头或结尾添加一个随机数,只需要一个两位数的十进制随机数就可以将关键字的写操作分布到100个不同的关键字,从而分配到不同的分区。

2. 分区与二级索引

二级索引通常不能唯一标识一条记录,而是用来加速特定值的查询。二级索引带来的主要挑战是它们不能规整地映射到分区中。有两种主要的方法来支持对二级索引进行分区:基于文档的分区和基于词条的分区。

基于文档分区的二级索引

在这种索引方法中,每个分区完全独立,各自维护自己的二级索引,且只负责自己分区内的文档而不关心其它分区中数据。文档分区索引也被称为本地索引,而不是全局索引。因此,这种查询分区数据库的方法有时也被称为分散/聚集,显然这种二级索引的查询代价高昂。即使采用了并行查询,也容易导致读延迟显著放大。

基于词条的二级索引分区

对所有的数据构建全局索引,而不是每个分区维护自己的本地索引。而且,为了避免成为瓶颈,不能将全局索引存储在一个节点上,否则就破坏了设计分区均衡的目标。所以,全局索引也必须进行分区,且可以与数据关键字采用不同的分区策略。

主要优点是:读取更加高效,它不需要采用scatter/gather对所有的分区都执行一遍查询。
主要缺点是:写入速度较慢且非常复杂,主要因为单个文档的更新时,里面可能会涉及多个二级索引,而二级索引的分区又可能完全不同甚至在不同的节点上,由此势必引入显著的写放大。

3. 分区再平衡

随着时间的推移,数据库可能总会出现某些变化:

(1)查询压力增大,因此需要更多的CPU来处理负载。
(2)数据规模增加,因此需要更多的磁盘和内存来存储数据。
(3)节点可能出现故障,因此需要其他机器来接管失效的节点。

所有这些变化都要求数据和请求可以从一个节点转移到另一个节点。这样一个迁移负载的过程称为再平衡。无论哪种分区方案,分区再平衡需要满足:

(1)平衡之后,负载、数据存储、读写请求等应该在集群范围内更均匀分布。
(2)再平衡执行过程中,数据库应该可以继续正常提供读写服务。
(3)避免不必要的负载迁移,以加快动态再平衡,并尽量减少网络和磁盘I/O影响。

动态再平衡的策略

  1. 固定数量的分区
    创建远超实际节点数的分区数,然后为每个节点分配多个分区。选中的整个分区会在节点之间迁移,但分区的总数量仍维持不变,也不会改变关键字到分区的映射关系。这里唯一需要调整的是分区和节点的对应关系。

  2. 动态分区
    设置固定边界、固定数量的分区非常不便,而手动重新配置分区边界又非常繁琐。因此,一些数据库如Hbase和RethinkDB采用了动态创建分区。当分区的数据增加超过一个可配的参数阈值,它就拆分成两个分区。每个承担一半的数据量。相反,如果大量数据被删除,并且分区缩小到某个阈值以下,则将其与相邻分区进行合并。

    动态分区的优点是:分区数量可以自动适配数据总量。

    动态分区的问题是:对于一个空的数据库,因为没有任何先验知识可以帮助确定分区的边界,所以可能会从一个分区开始。可能初始数据集很小,但直到第一个分裂点之前,所有的写入操作都必须由单个节点来处理,而其他节点则处于空闲状态。为了缓解这个问题,Hbase和MongoDB允许在一个空的数据库上配置一组初始分区(这称为预分裂)

  3. 按节点比例分区
    前面所讲的两种分区策略,分区数量都与节点数无关。固定数量的分区方式,每个分区的大小与数据集的大小成正比。动态分区方式,拆分和合并操作使每个分区的大小维持在设定的最小值和最大值之间,因此,分区数量和数据集大小成正比。而Cassandra和Ketama采用第三种方式,使分区数与集群节点数成正比关系。换句话,既是每个节点具有固定数量的分区。

4. 请求路由

现在我们已经将数据集分布到多个节点上,但是仍然有一个悬而未决的问题:当客户端需要发送请求时,如何知道应该连接哪个节点?同时,如果发生了分区再平衡,分区与节点的对应关系随之还会变化,如何确定?
概括来讲,有三种不同的处理策略;

  1. 允许客户端链接任意的节点(例如,采用循环式的负载均衡器)。随机选择一个节点,如果该节点恰好拥有所请求的分区,则直接处理该请求;否则,将请求转发到下一个合适的节点,接收答复,并将答复返回给客户端。
  2. 将所有客户端的请求都发送到一个路由层,由后者负责将请求转发到对应的分区节点上。路由层本身不处理任何请求,它仅仅充当一个分区感知的负载均衡器。
  3. 客户端自己感知分区和节点分配关系。此时,客户端可以直接连接到目标节点,而不需要任何中介。

这三种方法各有利弊,但是无论哪种方法,核心问题是:作出路由决策的组件,如何知道分区与节点的对应关系以及其变化情况?

这其实是一个很有挑战性的共识问题,所有参与者都要达成共识这一点很重要。在这里只讲一种分布式数据系统的典型方案:ZooKeeper

依靠独立的协调服务(如ZooKeeper)跟踪集群范围内的元数据。每个节点都向ZooKeeper中注册自己,ZooKeeper维护分区到节点的最终映射关系。其它参与者(如路由层或分区感知的客户端)可以向ZooKeeper订阅此消息。一旦分区发生了改变,或者添加、删除节点,ZooKeeper就会主动通知路由层,这样使路由信息保持最新状态。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值