浅谈HBase的数据分布

福利:国际顶级盛会HBaseCon Asia 2018将于8月在北京举行,目前正免费开放申请中,更多详情参考https://yq.aliyun.com/promotion/631

如果你对大数据存储、分布式数据库、HBase等感兴趣,欢迎加入我们,一起做最好的大数据在线存储,职位参考及联系方式:https://maimai.cn/job?webjid=1heZGIyM4&srcu=1aOrffoj1&src=app&fr=my_jobsrecruit_job

数据分布问题简述

分布式产生的根源是“规模”,规模可理解为计算和存储的需求。当单机能力无法承载日益增长的计算存储需求时,就要寻求对系统的扩展方法。通常有两种扩展方式:提升单机能力(scale up),增加机器(scale out,水平扩展)。限于硬件技术,单机能力的提升在一个阶段内是有上限的;而水平扩展在理论上可以是无限的,同时,也更廉价、更容易落地。水平扩展可以通过快速、简单的“加机器”,有效解决业务快速增长的问题,这几乎是现代分布式系统必备的能力。对于爆发式增长的业务,水平扩展似乎是唯一可选择的方案。

对于存储系统而言,原本存储在一台机器上的数据,现在要存放在多台机器上。此时必须解决两个问题:分片,复制。

数据分片(sharding),又称分区(partition),将数据集“合理的”拆分成多个分片,每台机器负责其中若干个分片。以此来突破单机容量的限制,同时也提升了整体的访问能力。另外,分片也降低了单个分片故障的影响范围。

数据复制(replica),也叫“副本”。分片无法解决单机故障丢数据的问题,所以,必然要通过冗余来解决系统高可用的问题。同时,副本机制也是提升系统吞吐、解决热点问题的重要手段。

分片和副本是正交的,这意味着我们可以只使用其中一种或都使用,但通常都是同时使用的。因为分片解决的是规模和扩展性的问题,副本解决可靠、可用性的问题。对于一个生产可用的系统,二者必须同时具备。

从使用者/客户端的角度看,分片和副本可以归结为同一个问题:请求路由,即请求应该发送给哪台机器来处理。

读数据时,能通过某种机制来确保有一个合适的分片/副本来提供服务

写数据时,能通过同样的机制来确保写到一个合适的地方,并确保副本的一致性

无论客户端的请求是直达服务端(如HBase/cassandra),还是通过代理(如公有云上的基于gateway的访问方式),请求路由都是分布式系统必须解决的问题。

无论是分片还是副本,本质上都是数据分布的体现。下面我们来看HBase的数据分布模型。

HBase的数据分布模型

HBase的数据分片按表进行,以行为粒度,基于rowkey范围进行拆分,每个分片称为一个region。一个集群有多张表,每张表划分为多个region,每台服务器服务很多region。所以,HBase的服务器称为RegionServer,简称RS。RS与表是正交的,即一张表的region会分布到多台RS上,一台RS也会调度多张表的region。如下图所示:

“以行为粒度”,意思是行是region划分的最小单位,即一行数据要么属于A region,要么属于Bregion,不会被拆到两个region中去。(对行进行拆分的方式是“垂直分库”,通常只能在业务层面进行,HBase是水平拆分)

HBase的副本机制是通过通过底层的HDFS实现的。所以,HBase的副本与分片是解耦的,是存储计算分离的。这使得region可以在RS之间灵活的移动,而不需要进行数据迁移,这赋予了HBase秒级扩容的能力和极大的灵活性。

对于单个表而言,一个“好”的数据分布,应该是每个region的数据量大小相近,请求量(吞吐)接近,每台机器调度的region数量大致相同。这样,这张表的数据和访问能够均匀的分布在整个集群中,从而得到最好的资源利用率和服务质量,即达到负载均衡。当集群进行扩容、缩容时,我们希望这种“均衡”能够自动保持。如果数据分布未能实现负载均衡,则负载较高的机器很容易称为整个系统的瓶颈,这台机器的响应慢,可能导致客户端的大部分线程都在等待这台机器返回,从而影响整体吞吐。所以,负载均衡是region划分和调度的重要目标。

这里涉及到3层面的负载均衡问题:

数据的逻辑分布:即region划分/分布,是rowkey到region的映射问题

数据的物理分布:即region在RS上的调度问题

访问的分布:即系统吞吐(请求)在各个RS上的分布问题,涉及数据量和访问量之间的关系,访问热点等。

可见,一行数据的分布(找到一行数据所在的RS),存在2个层级的路由:一是rowkey到region的路由,二是region到RS的路由。这一点是HBase能够实现灵活调度、秒级扩容的关键。后面我们会详细讨论。本文仅讨论前面两个问题,第三个问题放在后续的文章中讨论。

基于rowkey范围的region划分

首先,我们来看数据的逻辑分布,即一张表如何划分成多个region。

region划分的粒度是行,region就是这个表中多个连续的行构成的集合。行的唯一标识符是rowkey,所以,可以将region理解为一段连续分布的rowkey的集合。所以,称这种方式为基于rowkey范围的划分。

一个region负责的rowkey范围是一个左闭右开区间,所以,后一个region的start key是前一个region的end key。注意,第一个region是没有start key的,最后一个region是没有end key的。这样,这个表的所有region加在一起就能覆盖任意的rowkey值域。如下图所示:

上图中,region1是第一个region,没有startKey,region3是最后一个region,没有endKey。图中的region分布是比较均匀的,即每个region的行数是相当的,那么,这个分布是怎么得到的呢?或者说,region的边界是如何确定的?

一般来说,region的生成有3种方式:

建表时进行预分区:通过对rowkey进行预估,预先划分好region

region分裂:手工分裂,或达到一定条件时自动分裂(如region大小超过一个阈值)

region合并:手工合并

建表时如果未显式指定region分布,HBase就会只创建一个region,这个region自然也只能由一台机器进行调度(后面会讨论一个region由多个RS调度的情况)。那这个region的吞吐上限就是单机的吞吐上限。如果通过合理的预分区将表分成8个region,分布在8台RS上,那整表的吞吐上限就是8台机器的吞吐上限。

所以,为了使表从一开始就具备良好的吞吐和性能,实际生产环境中建表通常都需要进行预分区。但也有一些例外,比如无法预先对rowkey范围进行预估,或者,不容易对rowkey范围进行均匀的拆分,此时,也可以创建只有一个region的表,由系统自己分裂,从而逐渐形成一个“均匀的”region分布。

比如一张存储多个公司的员工信息的表,rowkey组成是orgId + userid,其中orgId是公司的id。由于每个公司的人数是不确定的,同时也可能是差别很大的,所以,很难确定一个region中包含几个orgId是合适的。此时,可以为其创建单region的表,然后导入初始数据,随着数据的导入进行region的自动分裂,通常都能得到比较理想的region分布。如果后续公司人员发生较大的变化,也可以随时进行region的分裂与合并,来获得最佳分布。

>>>>阅读全文

    原文作者:独角的犀牛
    原文地址: https://www.jianshu.com/p/f773f03dc9e6
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞