master启动过程:

-->首先初始化HMaster

-->创建一个rpcServer,其中并启动

-->启动一个Listener线程,功能是监听client的请求,将请求放入nio请求队列,逻辑如下:

-->创建n个selector,和一个n个线程的readpool,n由"ipc.server.read.threadpool.size"决定,默认为10

-->读取每个请求的头和内容,将内容放入priorityQueue中

-->启动一个Responder线程,功能是将响应队列里的数据写给各个client的connection通道,逻辑如下:

-->创建nio selector

-->默认超时时间为15 mins

-->依次将responseQueue中的内容写回各通道,并关闭连接

-->buffer=8k(代码写死)

-->如果该请求的返回没有写完,则放回队列头,推迟再发送

-->对于超时未完成的响应,丢弃并关闭相应连接

-->启动N(n默认为10)个Handler线程,功能是处理请求队列,并将结果写到响应队列

-->读取priorityQueue中的call,调用对应的call方法获得value,写回out并调用doRespond方法,处理该请求,并唤醒writable selector

-->启动M(m默认为0)个Handler线程以处理priority

-->注册zookeeper watcher

-->block直至成为active master 

-->先检查配置项"hbase.master.backup",自己是否backup机器,如果是则直接block直至检查到系统中的active master挂掉(默认每3分钟检查一次)

-->否则,注册zookeeper watcher,如果注册成功则成为active master,否则阻塞并反复通过watcher检查在运行的master是否挂掉或stop状态

-->进入finishInitialization()函数并初始化master: 

-->先检查hbase版本,如果是第一次启动hbase,则将版本信息写入/hbase/hbase.version,如果下次启动时这个文件不存在,则无法启动!如果不小心删掉了必须自己写一个版本 信息上去

--> 检查和保证root region的完好,如果root region还不存在,则创建root region以及第一个meta region

-->创建HConnectionImplementation实现的连接

-->创建server manager,后续绝大部分master工作都是通过server manager完成的

-->创建并启动CatalogTracker线程,用以跟踪root和meta两个特殊table的状态,它内部又启动RootRegionTracker和MetaNodeTracker两个线程

-->创建并启动RegionServerTracker线程,用以跟踪所有online region的状态,一旦有node delete状态则会通知server manager将其注销

-->创建并启动ClusterStatusTracker线程,用以跟踪整个cluster的up和down状态

-->向zookeeper注册AssignmentManager,用以管理region的分配

-->创建线程池ExecutorService,在其中运行以下线程

MASTER_META_SERVER_OPERATIONS

MASTER_SERVER_OPERATIONS

MASTER_CLOSE_REGION

MASTER_OPEN_REGION

MASTER_TABLE_OPERATIONS

--> 以守护方式运行LogCleaner线程,作用是每1分钟清理(.oldlogs)目录

--> 启动一个http server:InfoServer,作用是在60010端口上提供界面展示

--> 允许在初始化HMaster类时启动的Handler线程开始提供响应(通过开关标志)

-->然后master需要等待regionserver的报告,满足以下这些条件后返回当前所有region server上的region数后继续:

a 至少等待4.5s("hbase.master.wait.on.regionservers.timeout")

b 成功启动regionserver节点数>=1("hbase.master.wait.on.regionservers.mintostart")

c 1.5s内没有regionsever死掉或新启动("hbase.master.wait.on.regionservers.interval")

-->然后splitLogAfterStartup,从hlog中恢复数据,这是一个很长的逻辑:

-->依次检查每一个hlog目录,查看它所属的region server是否online,如果是则不需要做任何动作,region server自己会恢复数据,如果不是,则需要将它分配给其它 的region server

-->split是加锁操作:

--> 创建一个新的hlogsplitter,遍历每一个server目录下的所有hlog文件,依次做如下操作。(如果遇到文件损坏等无法跳过的错误,配 置"hbase.hlog.split.skip.errors=true"以忽略之)

-->启动"hbase.regionserver.hlog.splitlog.writer.threads"(默认为3)个线程,共使用128MB内存,启动这些写线程

-->先通过lease机制检查文件是否能够append,如果不能则死循环等待

-->把hlog中的内容全部加载到内存中(内存同时被几个写线程消费)

-->把有损坏并且跳过的文件移到/hbase/.corrupt/目录中

--> 把其余己经处理过的文件移到/hbase/.oldlogs中,然后删除原有的server目录

--> 等待写线程结束,返回新写的所有路径

-->解锁

写线程逻辑:

-->从内存中读出每一行数据的key和value,然后查询相应的region路径。如果该region路径不存在,说明该region很可能己经被split了,则不处理这部分数 据,因为此时忽略它们是安全的。

-->如果上一步能查到相应的路径,则到对应路径下创建"recovered.edits"文件夹(如果该文件夹存在则删除后覆盖之),然后将数据写入该文件夹

-->完成split Hlog的操作后,开始分配root和meta表:

-->分配root表:

-->block住直到root的region server从transaction状态中恢复正常

-->检查root的region server在zookeeper中是否己经有值并且正常可访问,如果不正常或没有则删除原有节点再重新分配(随机分配)

--> 分配meta表:

-->过程同root表的分配

-->如果启动后online的region servers上的regions总数为0,则表示这是个fresh start,清除掉zookeeper上的所有节点,重新开始watching

--> 开始分配user表

-->扫描meta中的所有表,依次分配,分配方案如下:

-->如果"hbase.master.startup.retainassign"为true(默认为true),则分配时按meta表中原有的信息来分配,即原来在哪里就还分到哪里,如果哪个region在原有的 server info中找不到所属的region server则从online region server中随机挑选

-->否则随机循环添加region,会保证balance

-->分配方案设计好后,开始执行分配的线程,默认超时时间10分钟

-->如果启动后online的region servers不为0,则表示很可能master挂掉过,可能是重新启动的。此时系统中己有region servers了,需要先处理region server上的regions:

-->转入processFailover处理流程

-->先调用rebuildUserRegions函数,它扫描.META.表,更新所有的server和对应的regionInfo信息,找出offline的server,加入deadServers

-->处理deadServers

-->遍历所有的region,在zk上创建它们的node,把它们加入transition和unassign列表,并置状态为offline

-->调用ServerShutdownHandler的processDeadRegion方法,处理所有dead regions

-->跳过所有disabled的table对应的region

-->查看该region是否己经split,如果是,需要fix它的子region

-->查看子region的info是否找不到了,如果是的话修补之(即重新将meta表中的region信息添加进来并assign它)

-->然后扫描zk中的transition列表,对不同的事件做不同处理

-->RS_ZK_REGION_CLOSING:将它简单添加到regionsInTransition队列中

-->RS_ZK_REGION_CLOSED:将它添加到regionsInTransition队列中并且创建一个ClosedRegionHandler线程去处理它

-->ClosedRegionHandler流程:

-->按root/meta/user region分优先级

-->如果这个region对应的table己经disabled或disabling,那么下线它并返回

-->下线这个region,然后再将它分配给一个server(不太明白为什么此时需要assign一次)

-->M_ZK_REGION_OFFLINE:同上

-->RS_ZK_REGION_OPENING:将它简单添加到regionsInTransition队列中

-->RS_ZK_REGION_OPENED:将它添加到regionsInTransition队列中,如果它对应的原来的RS还存在,则创建一个OpenedRegionHandler线程来处理,否则不处理,等待meta扫描时去分配它

-->OpenedRegionHandler流程:

-->按root/meta/user region分优先级

-->先删除zk中己经打开的对应的node

-->上线这个region

-->如果这个region对应的table己经disabled或disabling,那么unassign它

--> 启动balancer线程并放入守候线程,默认循环时间为300秒

    -->balancer线程的作用是定期均衡所有region server上的region数量,工作过程如下:

-->三种情况不进行balance:

-->balance开关没有打开(硬编码打开了)

-->有至少一个region正处于regionsInTransition状态(split结束但还没有清除)

-->有正在下线处理的region server

--> 制定出balance计划:

-->计算总的region数目,以及online server数量,每个server的region数目都会均衡到平均数。

-->执行balance计划:

--> 将执行计划放入assignment的执行计划列表

-->检查该region是否又进入了transaction状态,如果是则跳过

-->将该region置为pending_close状态

--> 向region server发送close region的信号

--> 真实执行计划在其它时候(下一篇文章介绍)

-->启动meta扫描线程并放入守候线程,默认循环时间为300秒

--> meta扫描线程的作用是定期清理己经split的region并将它删除,工作过程如下:

--> 连接meta server,scan表的info信息,扫描所有region,从region info中读出是否split的信息

-->如果己经split,则先获取splitA和splitB的region info

-->如果splitA和splitB的reference都不再指向父region了(从它们的regionPath可以得出),则将父region删除掉,删掉流程如下:

--> 将region的状态置为offline

-->将该region从regionsInTransition中删除掉

--> 将该region从regionPlan中删除掉,避免再进行balance之类的操作

-->将该region的region info从AssignmentManager的regions树中以及AssignmentManager中存放的每个servers中删掉

-->删除meta表里的该region的目录

-->通知meta region server删除该region

启动完成

HMaster的RPC接口,分两类:

HMaster与RegionServer通讯接口,总共只有两个

-->regionServerStartup: 当regionserver启动时会调用该接口

-->将发请起求的RS的信息写入serverInfo,注意这里的hostname为master所识别的hostname,而非RS告诉master的

-->调用serverManager的regionServerStartup方法处理该请求

-->check该RS是否deadServer,如果是,拒绝start请求,抛出YouAreDeadException异常

-->check该RS在同样的端口上是否己经启动,如果己经启动,通过serverInfo中的startcode来检查原来的RS是否可以注销,如果不能注销,拒绝请求,抛出PleaseHoldException异常

-->check该RS与master的时钟是否同步,如果相差太多(默认30s),拒绝请求并抛出ClockOutOfSyncException异常

-->注册该RS,具体要做的事有:

-->添加onlineServers

-->清除原有的serverConnections信息

-->将回应写入MapWritable结构,传回给RS

-->regionServerReport: regionserver心跳时调用该接口

-->调用ServerManager的regionServerReport方法,处理report并返回HMsg信息

-->check该RS是否deadServer,如果是,拒绝report请求,抛出YouAreDeadException异常

-->在onlineServers中查找该RS

-->如果找不到

-->check该RS在同样的端口上是否己经启动,如果己经启动,通过serverInfo中的startcode来检查原来的RS是否可以注销,如果不能注销,拒绝请求,抛出PleaseHoldException异常

-->注册一个新的RS

-->如果RS传过来的msg不会空,则抛出PleaseHoldException异常,推迟到下次report时再处理信息

-->如果找到的serverInfo和传过来的serverInfo的startCode不相同(不太可能发生)

-->删除serverInfo中的该server信息

-->向RS发送STOP_REGIONSERVER_ARRAY信号

-->检查传过来的msg,如果是REGION_SPLIT信号,调用getAssignmentManager的handleSplitReport方法,处理split事件

-->下线parent region

-->先把parent region从regionsInTransition状态中删除

-->清除与该parent region有关的regionPlan

-->下线该regions

-->从regions列表中删除它

-->从它所属的serverInfo中删除它对应的regionInfo

-->从己经zk上获得(parent所在的node)数据

-->如果它处于closing状态,删除它

-->从zk上得到它的数据

-->从hmaster的unassignedNodes中删除它

-->向zookeeper发请求删除该node

-->assign两个新的region

-->先清除regionsInTransition队列中的该子region

-->向regions中添加该region的regionInfo

-->向该serverInfo中添加该regionInfo

-->如果正好有跟该region相关的region plan,删除之

-->更新所有region plan中目的地是该RS且在regionsInTransition队列中的元素的state信息,这一步的目的是恢复region plan的有效性

-->如果此时正好用户在disable该region对应的表,需要把它unassign掉

-->更新该region在regionsInTransition中的状态为PENDING_CLOSE

-->调用serverManager的sendRegionClose方法,向RS发送colse region信号

-->如果cluster处理shutdown过程中,且剩余的RS小于等于2了,则发出STOP_REGIONSERVER_ARRAY信号,这是为了保证root和meta所在的RS最后关闭

HMaster的其它RPC接口:

-->isMasterRunning:检查master是否己stop

-->enableTable:

-->启动EnableTableHandler线程,执行handleEnableTable操作

-->调用setTableState,将table状态置为ENABLING

-->在zk上创建一个该table的znode

-->向zk通知该znode状态为ENABLING

-->更新cache中的该znode状态

-->读取.META.表,获取该table的所有region

-->跳过所有己经online的regions

-->创建一个BulkEnabler对象,用它分配所有regions

-->创建一个ExecutorService线程池完成这个工作

-->跳过所有处于transition状态的region

-->调用AssignmentManager的assign方法,注意这里会尽量延用原来在.META.表中的分配方案

-->等待分配的线程结束

-->调用setTableState,将table状态置为ENABLE

-->disableTable:

-->逻辑基本同enableTable,只是调用调用AssignmentManager的unassign方法

-->createTable:

-->强制不等待assign分配完成

-->如果没有指定splitKeys,那么只创建一个region,否则以splitKeys决定startKeys和endKeys,创建多个region

-->通知zk设置table状态为enabled

-->创建region,并在hdfs上创建它的目录

-->向meta所在的RS发送put,以注册.META.信息

-->close这个region,清空其对应的hlog

-->调用userregionassgin来分配它(robbin-round方式)

-->modifyTable:

-->启动modifyHandler线程修改table

-->通过CatalogTracker找到table对应的所有regionInfo

-->调用ModifyTableHandler,创建一个Put,把要修改的info放进去,然后调用connection去put

-->deleteTable:

-->逻辑基本同modifyTable,另外还增加fs上删除目录的操作

-->addColumn:

-->逻辑基本同modifyTable,另外还增加fs上创建目录的操作

-->modifyColumn:

-->逻辑基本同modifyTable,另外还增加fs上修改目录的操作

-->deleteColumn:

-->逻辑基本同modifyTable,另外还增加fs上删除目录的操作

-->shutdown:

-->调用serverManager的shutdownCluster方法关闭cluster

-->置clusterShutdown标志

-->调用master的stop方法

-->通知zookeeper关闭事件

-->stopMaster:置stop标志,并唤醒其它等待的backup master

-->getClusterStatus:返回cluster的信息,包括:版本号、live和dead的servers、transition的regions

-->move:将一个region移到一个确定的RS上

-->assign:分配一个region

-->unassign:卸载一个region

-->balance:直接执行一次balance

-->balanceSwitch:是否关闭balance功能(代码写死打开)

HBase Master启动过程的更多相关文章

  1. Ambari部署HDP:HBase Master启动后自动消失

    这是第一次出勤部署产品.遇到不可控问题,解决,写个心得.记录一下吧^^ 在排查问题的过程中,学到不少知识. (1)centos系统盘和数据盘分开,装操作系统的人没有将IT的空间分配出来,所以分区,自动 ...

  2. Hbase master启动报错:Failed construction of Master: class org.apache.hadoop.hbase.master.HMaster Caused by: java.net.UnknownHostException:

    Hbase master启动报错: java.lang.RuntimeException: Failed construction of Master: class org.apache.hadoop ...

  3. HBase Master 启动

    –>首先初始化HMaster –>创建一个rpcServer,其中并启动 –>启动一个Listener线程,功能是监听client的请求,将请求放入nio请求队列,逻辑如下: –&g ...

  4. hbase源码系列(六)HMaster启动过程

    这一章是server端开始的第一章,有兴趣的朋友先去看一下hbase的架构图,我专门从网上弄下来的. 按照HMaster的run方法的注释,我们可以了解到它的启动过程会去做以下的动作. * <l ...

  5. HBASE启动失败,Failed construction of Master: class org.apache.hadoop.hbase.master.HMaster

    Master日志错误:2015-12-02 06:34:32,394 ERROR [main] master.HMasterCommandLine: Master exitingjava.lang.R ...

  6. [原] KVM 虚拟化原理探究(2)— QEMU启动过程

    KVM 虚拟化原理探究- QEMU启动过程 标签(空格分隔): KVM [TOC] 虚拟机启动过程 第一步,获取到kvm句柄 kvmfd = open("/dev/kvm", O_ ...

  7. linux源码分析(二)-启动过程

    前置:这里使用的linux版本是4.8,x86体系. 这篇是 http://home.ustc.edu.cn/~boj/courses/linux_kernel/1_boot.html 的学习笔记. ...

  8. spark1.4.1 启动过程

    今天稍微没那么忙了,趁着这个时间,准备把spark的启动过程总结一下(),分享给大家.现在使用的spark1.4.1版本 当然前提是你已经把spark环境搭建好了. 1.我们启动spark的时候一般会 ...

  9. Linux启动过程详解(inittab、rc.sysinit、rcX.d、rc.local)

    启动第一步--加载BIOS 当你打开计算机电源,计算机会首先加载BIOS信息,BIOS信息是如此的重要,以至于计算机必须在最开始就找到它.这是因为BIOS中包含了CPU的相关信息.设备启动顺序信息.硬 ...

随机推荐

  1. Spring的DataSource配置、将Hibernate配置全部写到Spring配置

    DataSource可以集中管理数据库连接,减少维护工作量,使部署更简单: Spring的DataSource配置:(Spring数据源配置)这里使用dbcp,还有很多其他的如c3p0,jdbc,jn ...

  2. 19 Handler 总结

    Handler 一, 回顾异步任务 AsyncTask 二, android 使用线程的规则 1,在主线程 不能做阻塞操作 2,在主线程之外的线程不能更新Ui 三, Handler的作用 1,在子线程 ...

  3. JSP1.x 自定义标签

    Tag接口 任何一个标签都对应着一个java类,该类必须实现Tag接口,JSP遇到一个标签后后,将通过一个tld文件查找该标签的实现类,并运行该类的相关方法 import javax.servlet. ...

  4. 浅谈SSH框架

    在学习或者接触一个新的概念的时候,我们应该在脑海中发挥我们的搜索引擎,牵一发动全身的去想,这个知识跟我之前接触过的有哪些相同或者不同的地方,从这个角度去看那些新的知识和概念,经过旧知识和新知识的对比我 ...

  5. 6.2、Android Studio内存

    Android Monitor提供了一个Memory Monitor,所以你可以非常容易的监测应用性能和内存使用,可以发现无用的对象,本地内存泄漏和连接设备的内存使用.Memory Monitor显示 ...

  6. linux中Cron定时任务系统命令详解

    分类:Linux VPS教程 作者:阿川 发布时间:October 13, 2011 有很多同学在购买VPS之后,需要用到计划任务.但是又对计划任务不太了解,所以.今天我们的帮助中心主要是给大家提供一 ...

  7. Android简易实战教程--第十二话《代码获取手机总运行内存的大小》

    手机RAM存储,类似于电脑的内存.这一篇,对通过代码获取手机总内存大小做详细介绍. 首先,定义一个engine类,这个类功能就是获取进程信息,包括运行的程序个数,系统总内存,系统剩余总内存.本篇先完成 ...

  8. JQuery实战---窗口效果

    在前面的相关博文中,小编对jquery的相关知识进行了简单的总结,关于jquery的很多小的知识点,都需要我们自己去动手和实践,一行行代码都需要我们自己亲自动手去敲,今天我们继续来学习jquery的相 ...

  9. Scipy教程 - 优化和拟合库scipy.optimize

    http://blog.csdn.net/pipisorry/article/details/51106570 最优化函数库Optimization 优化是找到最小值或等式的数值解的问题.scipy. ...

  10. 自定义android 4.0以上的对话框风格

    做个笔记,这里是Dialog的风格,如果是用AlertDialog创建的,不能直接用.在styles.xml的写法: <style name="DialogWindowTitle&qu ...