深入解读HBase2.0新功能之AssignmentManagerV2

本文涉及的产品
云原生网关 MSE Higress,422元/月
服务治理 MSE Sentinel/OpenSergo,Agent数量 不受限
注册配置 MSE Nacos/ZooKeeper,118元/月
简介: AssignmentManager是HBase中一个非常重要的模块,负责Region在server上的状态变化,如Open、Close这些操作。HBase2.0中对AssignmentMananger做了重大重构,这边文章主要分析了之前AssignmentManager的问题,以及HBase2.

福利:国际顶级盛会HBaseCon Asia 2018将于8月在北京举行,目前正免费开放申请中
正在招聘:如果你对大数据存储、分布式数据库、HBase等感兴趣,欢迎加入我们,一起做最好的大数据在线存储:职位参考及联系方式

背景

AssignmentManager模块是HBase中一个非常重要的模块,Assignment Manager(之后简称AM)负责了HBase中所有region的Assign,UnAssign,以及split/merge过程中region状态变化的管理等等。在HBase-0.90之前,AM的状态全部存在内存中,自从HBASE-2485之后,AM把状态持久化到了Zookeeper上。在此基础上,社区对AM又修复了大量的bug和优化(见此文章),最终形成了用在HBase-1.x版本上的这个AM。

老Assignment Mananger的问题

相信深度使用过HBase的人一般都会被Region RIT的状态困扰过,长时间的region in transition状态简直令人抓狂。
image

除了一些确实是由于Region无法被RegionServer open的case,大部分的RIT,都是AM本身的问题引起的。总结一下HBase-1.x版本中AM的问题,主要有以下几点:

region状态变化复杂

image

这张图很好地展示了region在open过程中参与的组件和状态变化。可以看到,多达7个组件会参与region状态的变化。并且在region open的过程中多达20多个步骤!越复杂的逻辑意味着越容易出bug

region状态多处缓存

region的状态会缓存在多个地方,Master中RegionStates会保存Region的状态,Meta表中会保存region的状态,Zookeeper上也会保存region的状态,要保持这三者完全同步是一件很困难的事情。同时,Master和RegionServer都会修改Meta表的状态和Zookeeper的状态,非常容易导致状态的混乱。如果出现不一致,到底以哪里的状态为准?每一个region的transition流程都是各自为政,各自有各自的处理方法

重度依赖Zookeeper

在老的AM中,region状态的通知完全通过Zookeeper。比如说RegionServer打开了一个region,它会在Zookeeper把这个region的RIT节点改成OPEN状态,而不去直接通知Master。Master会在Zookeeper上watch这个RIT节点,通过Zookeeper的通知机制来通知Master这个region已经发生变化。Master再根据Zookeeper上读取出来的新状态进行一定的操作。严重依赖Zookeeper的通知机制导致了region的上线/下线的速度存在了一定的瓶颈。特别是在region比较多的时候,Zookeeper的通知会出现严重的滞后现象。

正是这些问题的存在,导致AM的问题频发。我本人就fix过多个AM导致region无法open的issue。比如说这三个相互关联的“连环”case:HBASE-17264,HBASE-17265,HBASE-17275

Assignment Mananger V2

面对这些问题的存在,社区也在不断尝试解决这些问题,特别是当region的规模达到100w级别的时候,AM成为了一个严重的瓶颈HBASE-11059中提出的ZK-less Region Assignment就是一个非常好的改良设计。在这个设计中,AM完全摆脱了Zookeeper的限制,在测试中,zk-less的assign比zk的assign快了一个数量级!
image

但是在这个设计中,它摒弃了Zookeeper这个持久化的存储,一些region transition过程中的中间状态无法被保存。因此,在此基础上,社区又更进了一步,提出了Assignment Mananger V2在这个方案。在这个方案中,仍然摒弃了Zookeeper参与Assignment的整个过程。但是,它引入了ProcedureV2这个持久化存储来保存Region transition中的各个状态,保证在master重启时,之前的assing/unassign,split等任务能够从中断点重新执行。具体的来说,AMv2方案中,主要的改进有以下几点:

Procedure V2

关于Procedure V2,我之后将独立写文章介绍。这里,我只大概介绍下ProcedureV2和引入它所带来的价值。
我们知道,Master中会有许多复杂的管理工作,比如说建表,region的transition。这些工作往往涉及到非常多的步骤,如果master在做中间某个步骤的时候宕机了,这个任务就会永远停留在了中间状态(RIT因为之前有Zookeeper做持久化因此会继续从某个状态开始执行)。比如说在enable/disable table时,如果master宕机了,可能表就停留在了enabling/disabling状态。需要一些外部的手段进行恢复。那么从本质上来说,ProcedureV2提供了一个持久化的手段(通过ProcedureWAL,一种类似RegionServer中WAL的日志持久化到HDFS上),使master在宕机后能够继续之前未完成的任务继续完成。同时,ProcedureV2提供了非常丰富的状态转换并支持回滚执行,即使执行到某一个步骤出错,master也可以按照用户的逻辑对之前的步骤进行回滚。比如建表到某一个步骤失败了,而之前已经在HDFS中创建了一些新region的文件夹,那么ProcedureV2在rollback的时候,可以把这些残留删除掉。
image

Procedure中提供了两种Procedure框架,顺序执行和状态机,同时支持在执行过程中插入subProcedure,从而能够支持非常丰富的执行流程。在AMv2中,所有的Assign,UnAssign,TableCreate等等流程,都是基于Procedure实现的。
image

去除Zookeeper依赖

有了Procedure V2之后,所有的状态都可以持久化在Procedure中,Procedure中每次的状态变化,都能够持久化到ProcedureWAL中,因此数据不会丢失,宕机后也能恢复。同时,AMv2中region的状态扭转(OPENING,OPEN,CLOSING,CLOSE等)都会由Master记录在Meta表中,不需要Zookeeper做持久化。再者,之前的AM使用的Zookeeper watch机制通知master region状态的改变,而现在每当RegionServer Open或者close一个region后,都会直接发送RPC给master汇报,因此也不需要Zookeeper来做状态的通知。综合以上原因,Zookeeper已经在AMv2中没有了存在的必要。

减少状态冲突的可能性

之前我说过,在之前的AM中,region的状态会同时存在于meta表,Zookeeper和master的内存状态。同时Master和regionserver都会去修改Zookeeper和meta表,维护状态统一的代价非常高,非常容易出bug。而在AMv2中,只有master才能去修改meta表。并在region整个transition中做为一个“权威”存在,如果regionserver汇报上来的region状态与master看到的不一致,则master会命令RegionServer abort。Region的状态,都以master内存中保存的RegionStates为准。

除了上述这些优化,AMv2中还有许多其他的优化。比如说AMv2依赖Procedure V2提供的一套locking机制,保证了对于一个实体,如一张表,一个region或者一个RegionServer同一时刻只有一个Procedure在执行。同时,在需要往RegionServer发送命令,如发送open,close等命令时,AMv2实现了一个RemoteProcedureDispatcher来对这些请求做batch,批量把对应服务器的指令一起发送等等。在代码结构上,之前处理相应region状态的代码散落在AssignmentManager这个类的各个地方,而在AMv2中,每个对应的操作,都有对应的Procedure实现,如AssignProcedure,DisableTableProcedure,SplitTableRegionProcedure等等。这样下来,使AssignmentManager这个之前杂乱的类变的清晰简单,代码量从之前的4000多行减到了2000行左右。

AssignProcedure

AMv2中有太多的Procedure对应各种不同的transition,这里不去详细介绍每个Procedure的操作。我将以AssignProcedure为例,讲解一下在AMv2中,一个region是怎么assign给一个RegionServer,并在对应的RS上Open的。
image

AssignProcedure是一个基于Procedure实现的状态机。它拥有3个状态:

  • REGION_TRANSITION_QUEUE: Assign开始时的状态。在这个状态时,Procedure会对region状态做一些改变和存储,并丢到AssignmentManager的assign queue中。对于单独region的assign,AssignmentManager会把他们group起来,再通过LoadBalancer分配相应的服务器。当这一步骤完成后,Procedure会把自己标为REGION_TRANSITION_DISPATCH,然后看是否已经分配服务器,如果还没有被分配服务器的话,则会停止继续执行,等待被唤醒。
  • REGION_TRANSITION_DISPATCH: 当AssignmentManager为这个region分配好服务器时,Procedure就会被唤醒。或者Procedure在执行完REGION_TRANSITION_QUEUE状态时master宕机,Procedure被恢复后,也会进入此步骤执行。所以在此步骤下,Procedure会先检查一下是否分配好了服务器,如果没有,则把状态转移回REGION_TRANSITION_QUEUE,否则的话,则把这个region交给RemoteProcedureDispatcher,发送RPC给对应的RegionServer来open这个region。同样的,RemoteProcedureDispatcher也会对相应的指令做一个batch,批量把一批region open的命令发送给某一台服务器。当命令发送完成之后,Procedure又会进入休眠状态,等待RegionServer成功OPen这个region后,唤醒这个Procedure
  • REGION_TRANSITION_FINISH: 当有RegionServer汇报了此region被打开后,会把Procedure的状态置为此状态,并唤醒Procedure执行。此时,AssignProcedure会做一些状态改变的工作,并修改meta表,把meta表中这个region的位置指向对应的RegionServer。至此,region assign的工作全部完成。

AMv2中提供了一个Web页面(Master页面中的‘Procedures&Locks’链接)来展示当前正在执行的Procedure和持有的锁。
其实通过log,我们也可以看到Assign的整个过程。
假设,一台server宕机,此时master会产生一个ServerCrashProcedure 来处理,在这个Procedure中,会做一系列的工作,比如WAL的restore。当这些前置的工作做完后,就会开始assign之前在宕掉服务器上的region,比如56f985a727afe80a184dac75fbf6860c。此时会在ServerCrashProcedure产生一系列的子任务:

2017-05-23 12:04:24,175 INFO  [ProcExecWrkr-30] procedure2.ProcedureExecutor: Initialized subprocedures=[{pid=1178, ppid=1176, state=RUNNABLE:REGION_TRANSITION_QUEUE; AssignProcedure table=IntegrationTestBigLinkedList, region=bfd57f0b72fd3ca77e9d3c5e3ae48d76, target=ve0540.halxg.cloudera.com,16020,1495525111232}, {pid=1179, ppid=1176, state=RUNNABLE:REGION_TRANSITION_QUEUE; AssignProcedure table=IntegrationTestBigLinkedList, region=56f985a727afe80a184dac75fbf6860c, target=ve0540.halxg.cloudera.com,16020,1495525111232}]

可以看到,ServerCrashProcedure的pid(Procedure ID)为1178,在此Procedure中产生的assign 56f985a727afe80a184dac75fbf6860c这个region的子Procedure的pid为1179,同时他的ppid(Parent Procedure ID)为1178。在AMv2中,通过追踪这些ID,就非常容易把一个region的transition整个过程全部串起来。
接下来,pid=1170这个Procedure开始执行,首先执行的是REGION_TRANSITION_QUEUE状态的逻辑,然后进入睡眠状态。

2017-05-23 12:04:24,241 INFO  [ProcExecWrkr-30] assignment.AssignProcedure: Start pid=1179, ppid=1176, state=RUNNABLE:REGION_TRANSITION_QUEUE; AssignProcedure table=IntegrationTestBigLinkedList, region=56f985a727afe80a184dac75fbf6860c, target=ve0540.halxg.cloudera.com,16020,1495525111232; rit=OFFLINE, location=ve0540.halxg.cloudera.com,16020,1495525111232; forceNewPlan=false, retain=false

当target server被指定时,Procedure进入REGION_TRANSITION_DISPATCH状态,dispatch了region open的请求,同时把meta表中region的状态改成了OPENING,然后再次进入休眠状态

2017-05-23 12:04:24,494 INFO  [ProcExecWrkr-38] assignment.RegionStateStore: pid=1179 updating hbase:meta row=IntegrationTestBigLinkedList,H\xE3@\x8D\x964\x9D\xDF\x8F@9'\x0F\xC8\xCC\xC2,1495566261066.56f985a727afe80a184dac75fbf6860c., regionState=OPENING, regionLocation=ve0540.halxg.cloudera.com,16020,1495525111232                                                2017-05-23 12:04:24,498 INFO  [ProcExecWrkr-38] assignment.RegionTransitionProcedure: Dispatch pid=1179, ppid=1176, state=RUNNABLE:REGION_TRANSITION_DISPATCH; AssignProcedure table=IntegrationTestBigLinkedList, region=56f985a727afe80a184dac75fbf6860c, target=ve0540.halxg.cloudera.com,16020,1495525111232; rit=OPENING, location=ve0540.halxg.cloudera.com,16020,1495525111232

最后,当RegionServer打开了这个region后,会发RPC通知master,那么在通知过程中,这个Procedure再次被唤醒,开始执行REGION_TRANSITION_FINISH的逻辑,最后更新meta表,把这个region置为打开状态。

2017-05-23 12:04:26,643 DEBUG [RpcServer.default.FPBQ.Fifo.handler=46,queue=1,port=16000] assignment.RegionTransitionProcedure: Received report OPENED seqId=11984985, pid=1179, ppid=1176, state=RUNNABLE:REGION_TRANSITION_DISPATCH; AssignProcedure table=IntegrationTestBigLinkedList, region=56f985a727afe80a184dac75fbf6860c, target=ve0540.halxg.cloudera.com,16020,1495525111232; rit=OPENING, location=ve0540.halxg.cloudera.com,16020,1495525111232                               2017-05-23 12:04:26,643 INFO  [ProcExecWrkr-9] assignment.RegionStateStore: pid=1179 updating hbase:meta row=IntegrationTestBigLinkedList,H\xE3@\x8D\x964\x9D\xDF\x8F@9'\x0F\xC8\xCC\xC2,1495566261066.56f985a727afe80a184dac75fbf6860c., regionState=OPEN, openSeqNum=11984985, regionLocation=ve0540.halxg.cloudera.com,16020,1495525111232
2017-05-23 12:04:26,836 INFO  [ProcExecWrkr-9] procedure2.ProcedureExecutor: Finish suprocedure pid=1179, ppid=1176, state=SUCCESS; AssignProcedure table=IntegrationTestBigLinkedList, region=56f985a727afe80a184dac75fbf6860c, target=ve0540.halxg.cloudera.com,16020,1495525111232

一路看下来,由于整个region assign的过程都是在Procedure中执行,整个过程清晰明了,非常容易追述,也没有了Zookeeper一些event事件的干扰。

总结

Assignment Mananger V2依赖Procedure V2实现了一套清晰明了的region transition机制。去除了Zookeeper依赖,减少了region状态冲突的可能性。整体上来看,代码的可读性更强,出了问题也更好查错。对于解决之前AM中的一系列“顽疾”,AMv2做了很好的尝试,也是一个非常好的方向。
AMv2之所以能保持简洁高效的一个重要原因就是重度依赖了Procedure V2,把一些复杂的逻辑都转移到了Procedure V2中。但是这样做的问题是:一旦ProcedureWAL出现了损坏,或者Procedure本身存在bug,这个后果就是灾难性的。事实上在我们的测试环境中,就出现过PRocedureWAL损坏导致region RIT的情况。
另外需要注意的是,截止目前为止,HBCK仍然无法支持AMv2,这会导致一旦出现问题,修复起来会比较困难。
当然,新的事务还是要有一段成熟期,相信经过一段时间的bug修复和完善后,我相信AMv2一定会完美解决之前的一些问题,给HBase的运维上带来一些不同的体验。愿世界不再被HBase的RIT困扰 :-)。

云端使用

阿里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版使用教程
  相关的阿里云产品:云数据库 HBase 版 面向大数据领域的一站式NoSQL服务,100%兼容开源HBase并深度扩展,支持海量数据下的实时存储、高并发吞吐、轻SQL分析、全文检索、时序时空查询等能力,是风控、推荐、广告、物联网、车联网、Feeds流、数据大屏等场景首选数据库,是为淘宝、支付宝、菜鸟等众多阿里核心业务提供关键支撑的数据库。 了解产品详情: https://cn.aliyun.com/product/hbase   ------------------------------------------------------------------------- 阿里云数据库体验:数据库上云实战 开发者云会免费提供一台带自建MySQL的源数据库 ECS 实例和一台目标数据库 RDS实例。跟着指引,您可以一步步实现将ECS自建数据库迁移到目标数据库RDS。 点击下方链接,领取免费ECS&RDS资源,30分钟完成数据库上云实战!https://developer.aliyun.com/adc/scenario/51eefbd1894e42f6bb9acacadd3f9121?spm=a2c6h.13788135.J_3257954370.9.4ba85f24utseFl
目录
相关文章
|
分布式计算 Hadoop 分布式数据库
HBase 部署
HBase 部署
123 0
|
存储 分布式数据库 API
hudi 0.9.0适配hbase 2.2.6
本文介绍hudi 0.9.0适配hbase 2.2.6指南
hudi 0.9.0适配hbase 2.2.6
|
存储 缓存 算法
生产环境使用HBase,你必须知道的最佳实践
生产环境使用HBase,你必须知道的最佳实践
282 0
|
NoSQL 固态存储 Java
HBase 1.0 之后在最近两年加的一些新功能
HBase作为BigTable的开源实现(之一,但也是应用最广的),其架构应该很多人即使完全没看过HBase的代码也都很清楚,毕竟干这个的几乎没人没读过BigTable的论文。但一个系统除了最基础的架构外还需要有一些细节的优化和实用的功能,很多功能大家就不见得了解了。因此感觉有必要介绍下最近两年HBase新增的一些比较重要的功能。以0.98为基准,在此假设0.98所包含的功能是大家所了解的,毕竟0.98.0是2014年2月发布了的。 HBase 1.0.0 在2015年2月发布后,首先最直观的改变是版本号采用了semantic versioning的语义,a.b.c的版本号,a major
162 0
|
运维 分布式数据库 Apache
HBase指南 | HBase 2.0之修复工具HBCK2运维指南
在之前的HBase版本中,我们可以依赖hbck来帮助检查问题和修复问题,在新的版本上我们应该如何去处理呢?HBASE-19121[1]给了我们答案——HBCK2。 HBCK2目前发布了1.0版本,还在一直开发中,感兴趣的同学看看这个issue。
8209 1
|
存储 分布式数据库 Hbase
技术篇-深入解读 HBase2.0 新功能之 AssignmentManagerV2
1.背景 AssignmentManager 模块是 HBase 中一个非常重要的模块,Assignment Manager (之后简称 AM)负责了 HBase 中所有 region 的 Assign,UnAssign,以及 split/merge 过程中 region 状态变化的管理等等。
2565 1
|
机器学习/深度学习 SQL 分布式计算
云HBase Phoenix索引构建最佳实践
介绍三种的不同的索引构建方法及其适用场景
2661 0
|
大数据 关系型数据库 分布式数据库
Hbase基础使用与云Hbase2.0体验
Hbase基础使用与云Hbase2.0体验以及基础使用
1797 0
|
存储 监控 算法
HBase行键设计
HBase行键设计
2265 0
下一篇
无影云桌面