摘要: AssignmentManager是HBase中一个很是重要的模块,负责Region在server上的状态变化,如Open、Close这些操做。HBase2.0中对AssignmentMananger作了重大重构,这边文章主要分析了以前AssignmentManager的问题,以及HBase2.
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。html
相信深度使用过HBase的人通常都会被Region RIT的状态困扰过,长时间的region in transition状态简直使人抓狂。缓存
除了一些确实是因为Region没法被RegionServer open的case,大部分的RIT,都是AM自己的问题引发的。总结一下HBase-1.x版本中AM的问题,主要有如下几点:安全
这张图很好地展现了region在open过程当中参与的组件和状态变化。能够看到,多达7个组件会参与region状态的变化。而且在region open的过程当中多达20多个步骤!越复杂的逻辑意味着越容易出bug服务器
region的状态会缓存在多个地方,Master中RegionStates会保存Region的状态,Meta表中会保存region的状态,Zookeeper上也会保存region的状态,要保持这三者彻底同步是一件很困难的事情。同时,Master和RegionServer都会修改Meta表的状态和Zookeeper的状态,很是容易致使状态的混乱。若是出现不一致,到底以哪里的状态为准?每个region的transition流程都是各自为政,各自有各自的处理方法框架
在老的AM中,region状态的通知彻底经过Zookeeper。好比说RegionServer打开了一个region,它会在Zookeeper把这个region的RIT节点改为OPEN状态,而不去直接通知Master。Master会在Zookeeper上watch这个RIT节点,经过Zookeeper的通知机制来通知Master这个region已经发生变化。Master再根据Zookeeper上读取出来的新状态进行必定的操做。严重依赖Zookeeper的通知机制致使了region的上线/下线的速度存在了必定的瓶颈。特别是在region比较多的时候,Zookeeper的通知会出现严重的滞后现象。less
正是这些问题的存在,致使AM的问题频发。我本人就fix过多个AM致使region没法open的issue。好比说这三个相互关联的“连环”case:HBASE-17264,HBASE-17265,HBASE-17275。运维
面对这些问题的存在,社区也在不断尝试解决这些问题,特别是当region的规模达到100w级别的时候,AM成为了一个严重的瓶颈。HBASE-11059中提出的ZK-less Region Assignment就是一个很是好的改良设计。在这个设计中,AM彻底摆脱了Zookeeper的限制,在测试中,zk-less的assign比zk的assign快了一个数量级!性能
可是在这个设计中,它摒弃了Zookeeper这个持久化的存储,一些region transition过程当中的中间状态没法被保存。所以,在此基础上,社区又更进了一步,提出了Assignment Mananger V2在这个方案。在这个方案中,仍然摒弃了Zookeeper参与Assignment的整个过程。可是,它引入了ProcedureV2这个持久化存储来保存Region transition中的各个状态,保证在master重启时,以前的assing/unassign,split等任务可以从中断点从新执行。具体的来讲,AMv2方案中,主要的改进有如下几点:测试
关于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的时候,能够把这些残留删除掉。优化
Procedure中提供了两种Procedure框架,顺序执行和状态机,同时支持在执行过程当中插入subProcedure,从而可以支持很是丰富的执行流程。在AMv2中,全部的Assign,UnAssign,TableCreate等等流程,都是基于Procedure实现的。
有了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行左右。
AMv2中有太多的Procedure对应各类不一样的transition,这里不去详细介绍每一个Procedure的操做。我将以AssignProcedure为例,讲解一下在AMv2中,一个region是怎么assign给一个RegionServer,并在对应的RS上Open的。
AssignProcedure是一个基于Procedure实现的状态机。它拥有3个状态:
AMv2中提供了一个Web页面(Master页面中的‘Procedures&Locks’连接)来展现当前正在执行的Procedure和持有的锁。
其实经过log,咱们也能够看到Assign的整个过程。
假设,一台server宕机,此时master会产生一个ServerCrashProcedure 来处理,在这个Procedure中,会作一系列的工做,好比WAL的restore。当这些前置的工做作完后,就会开始assign以前在宕掉服务器上的region,好比56f985a727afe80a184dac75fbf6860c。此时会在ServerCrashProcedure产生一系列的子任务:
能够看到,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状态的逻辑,而后进入睡眠状态。
当target server被指定时,Procedure进入REGION_TRANSITION_DISPATCH状态,dispatch了region open的请求,同时把meta表中region的状态改为了OPENING,而后再次进入休眠状态
最后,当RegionServer打开了这个region后,会发RPC通知master,那么在通知过程当中,这个Procedure再次被唤醒,开始执行REGION_TRANSITION_FINISH的逻辑,最后更新meta表,把这个region置为打开状态。
一路看下来,因为整个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/produc...
同时,云HBase2.0 在2018年6月6日正式发布,点击了解更多: https://promotion.aliyun.com/...
本文做者:正研
阅读原文本文为云栖社区原创内容,未经容许不得转载。