深入解读HBase2.0新功能之高可用读Region Replica

简介: 基于时间线一致的高可用读(Timeline-consistent High Available Reads),又称Region replica,为HBase带来了高可用读的能力。本文主要介绍region replica这个功能设计的背景,技术细节和使用方法,同时会仔细分析这个功能的优缺点并给出使用建议。

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

正在招聘:如果你对大数据存储、分布式数据库、HBase等感兴趣,欢迎加入我们,一起做最好的大数据在线存储: 职位参考及联系方式

前言

基于时间线一致的高可用读(Timeline-consistent High Available Reads),又称Region replica。其实早在HBase-1.2版本的时候,这个功能就已经开发完毕了,但是还是不太稳定,离生产可用级别还有一段距离,后来社区又陆陆续续修复了一些bug,比如说HBASE-18223。这些bug很多在HBase-1.4之后的版本才修复,也就是说region replica功能基本上在HBase-1.4之后才稳定下来。介于HBase-1.4版本目前实际生产中使用的还比较少,把region replica功能说成是HBase2.0中的新功能也不为过。

为什么需要Region Replica

CAP理论中,HBase一直是一个CP(Consistency&Partition tolerance)系统。HBase一直以来都在遵循着读写强一致的语义。所以说虽然在存储层,HBase依赖HDFS实现了数据的多副本,但是在计算层,HBase的region只能在一台RegionServer上线提供读写服务,来保持强一致。如果这台服务器发生宕机时,Region需要从WAL中恢复还缓存在memstore中未刷写成文件的数据,才能重新上线服务。
image

由于HBase的RegionServer是使用Zookeeper与Master保持lease。而为了不让JVM GC停顿导致RegionServer被master“误判”死亡,这个lease时间通常都会设置为20~30s,如果RegionServer使用的Heap比较大时,这个lease可能还会设的更长。加上宕机后,region需要re-assign,WAL可能需要 recoverlease和被replay操作,一个典型的region宕机恢复时间可能长达一分钟!这就意味着在这一分钟内,这个region都无法被读写。由于HBase是一个分布式系统,同一张表的数据可能分布在非常多的RegionServer和region里。如果这是一个大HBase集群,有100台RegionServer机器,那么宕机一台的话,可能只有1%的用户数据被影响了。但是如果这是小用户的HBase集群,一共就只有2台RegionServer,宕机一台意味着50%的用户数据都在1~2分钟之内无法服务,这是很多用户都无法忍受的。

其实,很大一部分用户对读可用性的需求,可能比读强一致的需求还要高。在故障场景下,只要保证读继续可用,“stale read”,即读到之前的数据也可以接受。这就是为什么我们需要read replica这个功能。

Region Replica技术细节

Region replica的本质,就是让同一个region host在多个regionserver上。原来的region,称为Default Replica(主region),提供了与之前类似的强一致读写体验。而与此同时,根据配置的多少,会有一个或者多个region的副本,统称为 region replica,在另外的RegionServer上被打开。并且由Master中的LoadBalancer来保证region和他们的副本,不会在同一个RegionServer打开,防止一台服务器的宕机导致多个副本同时挂掉。
image

Region Replica的设计巧妙之处在于,额外的region副本并不意味着数据又会多出几个副本。这些region replica在RegionServer上open时,使用的是和主region相同的HDFS目录。也就是说主region里有多少HFile,那么在region replica中,这些数据都是可见的,都是可以读出来的。
region replica相对于主region,有一些明显的不同。
首先,region replica是不可写的。这其实很容易理解,如果region replica也可以写的话,那么同一个region会在多个regionserver上被写入,连主region上的强一致读写都没法保证了。
再次,region replica是不能被split和merge的。region replica是主region的附属品,任何发向region replica的split和merge请求都会被拒绝掉。只有当主region split/merge时,才会把这些region replica从meta表中删掉,建立新生成region的region的replica。

replica之间的数据同步

那么,既然region replica不能接受写,它打开之后,怎么让新写入的数据变的可见呢?这里,region replica有两种更新数据的方案:

1. 定期的StoreFile Refresher

这个方案非常好理解,region replica定期检查一下它自己对应的HDFS目录,如果发现文件有变动,比如说flush下来新的文件,文件被compaction掉,它就刷新一下自己的文件列表,这个过程非常像compaction完成之后删除被compact掉的文件和加入新的文件的流程。StoreFile Refresher方案非常简单,只需要在RegionServer中起一个定时执行的Chroe,定期去检查一下它上面的region哪些是region replica,哪些到了设置好的刷新周期,然后刷新就可以了。但这个方案缺点也十分明显,主region写入的数据,只有当flush下来后,才能被region replica看到。而且storeFile Refresher本身还有一个刷新的周期,设的太短了,list文件列表对NN的冲击太频繁,设的太长,就会造成数据长时间在region replica中都不可见

2. Internal Replication

我们知道,HBase是有replication链路的,支持把一个HBase集群的数据通过replication复制到另外一个集群。那么,同样的原理,可以在HBase集群内部建立一条replication通道,把一个Server上的主region的数据,复制到另一个Server的region replica上。那么region replica接收到这些数据之后,会把他们写入memstore中。对,你没看错,刚才我说了region replica是不接受写的,这是指replica不接受来自客户端的写,如果来自主region的replication的数据,它还是会写入memstore的。但是,这个写和普通的写有很明显的区别。第一个,replica region在写入来自主region的时候,是不写WAL的,因为这些数据已经在主region所在的WAL中持久化了,replica中无需再次落盘。第二个,replica region的memstore中的数据是不会被flush成HFile。我们知道,HBase的replication是基于复制WAL文件实现的,那么在主region进行flush时,也会写入特殊的标记Flush Marker。当region replica收到这样的标记时,就直接会把所有memstore里的数据丢掉,再做一次HDFS目录的刷新,把主region刚刚刷下去的那个HFile include进来。同样,如果主region发生了compaction,也会写入相应的Compaction Marker。读到这样的标记后,replica region也会做类似的动作。

Internal replication加快了数据在region replica中的可见速度。通过replication方案,只要replication本身不发生阻塞和延迟,region replica中的数据可以做到和主region只差几百ms。但是,replication方案本身也存在几个问题:

  • META表 无法通过replication来同步数据
    如果给meta表开了region replica功能,meta表主region和replica之间的数据同步,只能通过定期的StoreFile Refresher机制。因为HBase的replication机制中会过滤掉meta表的数据。
  • 需要消耗额外的CPU和网络带宽来做Replication
    由于region replica的数据同步需要,需要在HBase集群内部建立replication通道,而且有几个replica,就意味着需要从主region发送几份数据。这会增加RegionServer的CPU使用,同时在server之间复制数据还需要占用带宽
  • 写memstore需要额外的内存开销
    为了让replica region的数据缺失的内容尽量的少,主region的数据会通过replication发送到replica中,这些数据都会保存在memstore中。也就是说同样的一份数据,会同时存在主region的memstore中,也会存在replica region的memstore中。replica的数量是几,那么memstore的内存使用量就是几倍。

下面的两个问题虽然可以通过配置一些参数解决,但是列在这里,仍然需要注意,因为一旦参数没有配对,就会产生这样的问题。

  • 在replica region failover后,读到的数据可能会回退
    我们假设一个情况。客户端写入X=1,主region发生flush,X=1刷在了HFile中,然后客户端继续写入X=2,X=3,那么在主region的memstore中X=3。同时,通过replication,X=2,X=3也被复制到了replica region的memstore中。如果客户端去replica中去读取X的数据,也能读到3。但是由于replica region memstore中的数据是不写WAL的,也不刷盘。那么当replica所在的机器宕机后,它是没有任何数据恢复流程的,他会直接在其他RegionServer上线。上线后它只能读取HFile,无法感知主region memstore里的数据。这时如果客户端来replica上读取数据,那么他只会读到HFile中的X=1。也就是说之前客户端可以读到X=3,但后来却只能读到X=1了,数据出现了回退。为了避免出现这样的问题,可以配置一个hbase.region.replica.wait.for.primary.flush=true的参数,配置之后,replica region上线后,会被标记为不可读,同时它会去触发一次主region的flush操作。只有收到主region的flush marker之后,replica才把自己标记为可读,防止读回退
  • replica memstore过大导致写阻塞
    上面说过,replica的region中memstore是不会主动flush的,只有收到主region的flush操作,才会去flush。同一台RegionServer上可能有一些region replica和其他的主region同时存在。这些replica可能由于复制延迟(没有收到flush marker),或者主region没有发生flush,导致一直占用内存不释放。这会造成整体的内存超过水位线,导致正常的写入被阻塞。为了防止这个问题的出现,HBase中有一个参数叫做hbase.region.replica.storefile.refresh.memstore.multiplier,默认值是4。这个参数的意思是说,如果最大的replica region的memstore已经超过了最大的主region memstore的内存的4倍,就主动触发一次StoreFile Refresher去更新文件列表,如果确实发生了flush,那么replica内存里的数据就能被释放掉。但是,这只是解决了replication延迟导致的未flush问题,如果这个replica的主region确实没有flush过,内存还是不能被释放。写入阻塞还是会存在

Timeline Consistency Read

无论是StoreFile Refresher还是Internal replication,主region和replica之间的数据更新都是异步的,这就导致在replica region中读取数据时,都不是强一致的。read replica的作者把从region replica中读数据的一致性等级定为Timeline Consistency。只有用户明确表示能够接受Timeline consistency,客户端的请求才会发往replica中。
image

比如说上图中,如果客户端是需要强一致读,那么客户端的请求只会发往主region,即replica_id=0的region,他就会读到X=3.如果他选择了Timeline consistency读,那么根据配置,他的读可能落在主上,那么他仍然会读到X=3,如果他的读落在了replica_id=1的region上,因为复制延迟的存在,他就只能读到X=2.如果落在了replica_id=2上,由于replication链路出现了问题,他就只能读到X=1。

Region replica的使用方法

服务端配置

hbase.regionserver.storefile.refresh.period

如果要使用StoreFile Refresher来做为Region replica之间同步数据的策略,就必须把这个值设置为一个大于0的数,即刷新storefile的间隔周期(单位为ms)上面的章节讲过,这个值要不能太大,也不能太小。

hbase.regionserver.meta.storefile.refresh.period

由于Meta表的region replica不能通过replication来同步,所以如果要开启meta表的region replica,必须把这个参数设成一个不为0的值,具体作用参见上一个参数,这个参数只对meta表生效。

hbase.region.replica.replication.enabled
hbase.region.replica.replication.memstore.enabled

如果要使用Internal replication的方式在Region replica之间同步数据的策略,必须把这两个参数都设置为true

hbase.master.hfilecleaner.ttl

在主region发生compaction之后,被compact掉的文件会放入Achieve文件夹内,超过hbase.master.hfilecleaner.ttl时间后,文件就会被从HDFS删除掉。而此时,可能replica region正在读取这个文件,这会造成用户的读取抛错返回。如果不想要这种情况发生,就可以把这个参数设为一个很大的值,比如说3600000(一小时),总没有读操作需要读一个小时了吧?

hbase.meta.replica.count

mata表的replica份数,默认为1,即不开启meta表的replica。如果想让meta表有额外的一个replica,就可以把这个值设为2,依次类推。此参数只影响meta表的replica份数。用户表的replica份数是在表级别配置的,这个我后面会讲

hbase.region.replica.storefile.refresh.memstore.multiplier

这个参数我在上面的章节里有讲,默认为4

hbase.region.replica.wait.for.primary.flush

这个参数我在上面的章节里有讲,默认为true

需要注意的是,开启region replica之后,Master的balancer一定要用默认的StochasticLoadBalancer,只有这个balancer会尽量使主region和他的replica不在同一台机器上。其他的balaner会无区别对待所有的region。

客户端配置

hbase.ipc.client.specificThreadForWriting

因为当存在region replica时,当客户端发往主region的请求超时后,会发起一个请求到replica region,当其中一个请求放回后,就无需再等待另一个请求的结果了,通常要中断这个请求,使用专门的的线程来发送请求,比较容易处理中断。所以如果要使用region replica,这个参数要配为true。

hbase.client.primaryCallTimeout.get
hbase.client.primaryCallTimeout.multiget
hbase.client.replicaCallTimeout.scan

分别对应着,get、multiget、scan时等待主region返回结果的时间。如果把这个值设为1000ms,那么客户端的请求在发往主region超过1000ms还没返回后,就会再发一个请求到replica region(如果有多个replica的话,就会同时发往多个replica)

hbase.meta.replicas.use

如果服务端上开启了meta表的replica后,客户端可以使用这个参数来控制是否使用meta表的replica的region。

建表

在shell建表时,只需在表的属性里加上REGION_REPLICATION => xx就可以了,如

create 't1', 'f1', {REGION_REPLICATION => 2}

Replica的份数支持动态修改,但修改之前必须disable表

diable 't1'
alter 't1', {REGION_REPLICATION => 1}
enable 't1'

访问有replica的表

如果可以按请求设置一致性级别,如果把请求的一致性级别设为Consistency.TIMELINE,即有可能读到replica上

Get get1 = new Get(row);
get1.setConsistency(Consistency.TIMELINE);
...
ArrayList<Get> gets = new ArrayList<Get>();
gets.add(get1);
...
Result[] results = table.get(gets);

另外,用户可以通过Result.isStale()方法来获得返回的result是否来自主region,如果为isStale为false,则结果来自主region。

Result result = table.get(get);
if (result.isStale()) {
...
}

总结和建议

Region Replica功能给HBase用户带来了高可用的读能力,提高了HBase的可用性,但同时也存在一定的缺点:

  • 高可用的读基于Timeline consistency,用户需要接受非强一致性读才能开启这个功能
  • 使用Replication来做数据同步意味着额外的CPU,带宽消耗,同时根据replica的多少,可能会有数倍的memstore内存消耗
  • 读取replica region中的block同样会进block cache(如果表开启了block cache的话),这意味着数倍的cache开销
  • 客户端Timeline consistency读可能会把请求发往多个replica,可能带来更多的网络开销

Region Replica只带来了高可用的读,宕机情况下的写,仍然取决于主region的恢复时间,因此MTTR时间并没有随着使用Region replica而改善。虽然说region replica的作者在规划中有写计划在宕机时把一个replica提升为主,来优化MTTR时间,但截至目前为止,还没有实现。

个人建议,region replica功能适合于用户集群规模较小,对读可用性非常在意,同时又可以接受非强一致性读的情况下开启。如果集群规模较大,或者读写流量非常大的集群上开启此功能,需要留意内存使用和网络带宽。Memstore占用内存过高可能会导致region频繁刷盘,影响写性能,同时cache容量的翻倍会导致一部分读请求击穿cache直接落盘,导致读性能的下降。

云端使用

阿里HBase目前已经在阿里云提供商业化服务,任何有需求的用户都可以在阿里云端使用深入改进的、一站式的HBase服务。云HBase版本与自建HBase相比在运维、可靠性、性能、稳定性、安全、成本等方面均有很多的改进,更多内容欢迎大家关注 https://www.aliyun.com/product/hbase
同时,云HBase2.0 在2018年6月6日将正式发布,点击了解更多: https://promotion.aliyun.com/ntms/act/hbase20.html

相关实践学习
lindorm多模间数据无缝流转
展现了Lindorm多模融合能力——用kafka API写入,无缝流转在各引擎内进行数据存储和计算的实验。
云数据库HBase版使用教程
&nbsp; 相关的阿里云产品:云数据库 HBase 版 面向大数据领域的一站式NoSQL服务,100%兼容开源HBase并深度扩展,支持海量数据下的实时存储、高并发吞吐、轻SQL分析、全文检索、时序时空查询等能力,是风控、推荐、广告、物联网、车联网、Feeds流、数据大屏等场景首选数据库,是为淘宝、支付宝、菜鸟等众多阿里核心业务提供关键支撑的数据库。 了解产品详情:&nbsp;https://cn.aliyun.com/product/hbase &nbsp; ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库&nbsp;ECS 实例和一台目标数据库&nbsp;RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&amp;RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
2月前
|
存储 分布式计算 Hadoop
Hadoop-33 HBase 初识简介 项目简介 整体架构 HMaster HRegionServer Region
Hadoop-33 HBase 初识简介 项目简介 整体架构 HMaster HRegionServer Region
55 2
|
存储 分布式计算 监控
分布式数据库HBase的基本概念和架构之基本架构的Region Server
分布式数据库HBase是一个开源的分布式数据库系统,是Apache Hadoop生态系统的重要组成部分。
415 0
|
分布式数据库 Hbase
|
存储 缓存 容灾
HBase可用性分析与高可用实践
HBase可用性分析与高可用实践
334 0
HBase可用性分析与高可用实践
|
Hbase 分布式数据库 监控
阿里HBase高可用8年“抗战”回忆录
2018年双十一,HBase全天处理请求2.4万亿行,单集群吞吐达到千万级别。从一个婴儿成长为青年,阿里HBase摔过很多次,甚至头破血流,我们在客户的信任之下幸运的成长,感激涕零。2017年开始阿里HBase走向公有云,我们有计划的在逐步将阿里内部的高可用技术提供给外部客户,目前已经上线同城主备
2720 0
阿里HBase高可用8年“抗战”回忆录
|
存储 缓存 容灾
HBase可用性分析与高可用实践
云栖号资讯:【点击查看更多行业资讯】在这里您可以找到不同行业的第一手的上云资讯,还在等什么,快来! HBase作为一个分布式存储的数据库,它是如何保证可用性的呢?对于分布式系统的CAP问题,它是如何权衡的呢? 最重要的是,我们在生产实践中,又应该如何保证HBase服务的高可用呢? 下面我们来仔细分析一下。
HBase可用性分析与高可用实践
|
存储 机器学习/深度学习 弹性计算
独家支持用户自建、混合云环境集群,快收下这份HBase高可用解决方案
&gt; 简介:阿里云HBase服务了多家金融、广告、媒体类业务中的风控和推荐,持续的在高可用、低延迟、低成本方向上进行优化。 &gt; &gt; 为了进一步满足客户在可用性以及低延迟上的诉求,阿里云HBase将提供以主备架构为平台,以冗余、并发、隔离、降级等全方位服务为支撑的高可用解决方案。
1715 0
独家支持用户自建、混合云环境集群,快收下这份HBase高可用解决方案
|
Hbase 分布式数据库 存储
阿里云HBase推出普惠性高可用服务,独家支持用户的自建、混合云环境集群
阿里云HBase服务了多家金融、广告、媒体类业务中的风控和推荐,持续的在高可用、低延迟、低成本方向上进行优化。为了进一步满足客户在可用性以及低延迟上的诉求,阿里云HBase将提供以主备架构为平台,以冗余、并发、隔离、降级等全方位服务为支撑的高可用解决方案。
5378 0
阿里云HBase推出普惠性高可用服务,独家支持用户的自建、混合云环境集群