美文网首页深入理解HBASE
深入理解HBASE(3.3)RegionServer-Regio

深入理解HBASE(3.3)RegionServer-Regio

作者: 宋大壮 | 来源:发表于2019-03-24 17:26 被阅读0次

    作用

    – HBase自动把表水平划分成多个区域(region),每个region会保存一个表 里面某段连续的数据;每个表一开始只有一个region,随着数据不断插 入表,

    • region不断增大,当增大到一个阀值的时候,region就会等分会 两个新的region(裂变);

    – 当table中的行不断增多,就会有越来越多的region。这样一张完整的表 被保存在多个Regionserver上。

    层级结构

    • Table (HBase 表)

    • Region(表的Regions)

      • Store(Region中以列族为单位的单元)

        • MemStore (用于写缓存)

        • StoreFile (StoreFiles for each Store for each Region for the table) 存储在磁盘上的文件(HFile)

          • Block (读写的最小单元)

    Region分裂

    1、根据rowkey来分裂定位切分点

    那切分点是如何定位的呢? 整个region中最大store中的最大文件中最中心的一个block的首个rowkey 。这是一句比较消耗脑力的语句,需要细细品味。另外,HBase还规定,如果定位到的rowkey是整个文件的首个rowkey或者最后一个rowkey的话,就认为没有切分点。

    什么情况下会出现没有切分点的场景呢?最常见的就是一个文件只有一个block,执行split的时候就会发现无法切分。很多新同学在测试split的时候往往都是新建一张新表,然后往新表中插入几条数据并执行一下flush,再执行split,奇迹般地发现数据表并没有真正执行切分。原因就在这里,这个时候仔细的话你翻看debug日志是可以看到这样的日志滴:

    分割日志

    2、事务性执行分裂

    HBase将整个切分过程包装成了一个事务,意图能够保证切分事务的原子性。整个分裂事务过程分为三个阶段:prepare – execute – (rollback) ,操作模版如下:

    执行分裂的代码

    prepare阶段:

    在内存中初始化两个子region,具体是生成两个HRegionInfo对象,包含tableName、regionName、startkey、endkey等。同时会生成一个transaction journal,这个对象用来记录切分的进展,具体见rollback阶段。

    执行阶段

    1. regionserver 更改ZK节点 /region-in-transition 中该region的状态为SPLITING。

    2. master通过watch节点/region-in-transition检测到region状态改变,并修改内存中region的状态,在master页面RIT模块就可以看到region执行split的状态信息。

    3. 在父存储目录下新建临时文件夹.split保存split后的daughter region信息。

    4. 关闭parent region:parent region关闭数据写入并触发flush操作,将写入region的数据全部持久化到磁盘。此后短时间内客户端落在父region上的请求都会抛出异常NotServingRegionException。

    5. 核心分裂步骤:在.split文件夹下新建两个子文件夹,称之为daughter A、daughter B,并在文件夹中生成reference文件,分别指向父region中对应文件。这个步骤是所有步骤中最核心的一个环节,生成reference文件日志如下所示:

    2017-08-12 11:53:38,158 DEBUG [StoreOpener-0155388346c3c919d3f05d7188e885e0-1] regionserver.StoreFileInfo: reference 'hdfs://hdfscluster/hbase-rsgroup/data/default/music/0155388346c3c919d3f05d7188e885e0/cf/d24415c4fb44427b8f698143e5c4d9dc.00bb6239169411e4d0ecb6ddfdbacf66' to region=00bb6239169411e4d0ecb6ddfdbacf66 hfile=d24415c4fb44427b8f698143e5c4d9dc。

    reference文件是一个引用文件(并非linux链接文件),文件内容很显然不是用户数据。

    文件内容其实非常简单,主要有两部分构成:

    其一是切分点 splitkey

    其二是一个boolean类型的变量(true或者false),true表示该reference文件引用的是父文件的上半部分(top),而false表示引用的是下半部分 (bottom)。

    原理
    1. 父region分裂为两个子region后, 将daughter A、daughter B拷贝到HBase根目录下,形成两个新的region

    2. parent region通知修改 hbase.meta 表后下线,不再提供服务。下线后parent region在meta表中的信息并不会马上删除,而是标注split列、offline列为true,并记录两个子region。

    3. 开启daughter A、daughter B两个子region。通知修改 hbase.meta 表,正式对外提供服务。

    rollback阶段:

    如果execute阶段出现异常,则执行rollback操作。为了实现回滚,整个切分过程被分为很多子阶段,回滚程序会根据当前进展到哪个子阶段清理对应的垃圾数据。代码中使用 JournalEntryType 来表征各个子阶段,

    分裂问题

    1、通过reference文件如何查找数据?

    (1)根据reference文件名(region名+真实文件名)定位到真实数据所在文件路径

    (2)定位到真实数据文件就可以在整个文件中扫描待查KV了么?非也。因为reference文件通常都只引用了数据文件的一半数据,以切分点为界,要么上半部分文件数据,要么下半部分数据。那到底哪部分数据?切分点又是哪个点?还记得上文又提到reference文件的文件内容吧,没错,就记录在文件中。

    文件内容其实非常简单,主要有两部分构成:其一是切分点 splitkey,其二是一个boolean类型的变量(true或者false),true表示该reference文件引用的是父文件的上半部分(top),而false表示引用的是下半部分 (bottom)。

    2、父region的数据什么时候会迁移到子region目录?

    答案是子region发生major_compaction时。我们知道compaction的执行实际上是将store中所有小文件一个KV一个KV从小到大读出来之后再顺序写入一个大文件,完成之后再将小文件删掉,因此compaction本身就需要读取并写入大量数据。子region执行major_compaction后会将父目录中属于该子region的所有数据读出来并写入子region目录数据文件中。可见将数据迁移放到compaction这个阶段来做,是一件顺便的事。

    3、父region什么时候会被删除?

    实际上HMaster会启动一个线程定期遍历检查所有处于splitting状态的父region,确定检查父region是否可以被清理。检测线程首先会在meta表中揪出所有split列为true的region,并加载出其分裂后生成的两个子region(meta表中splitA列和splitB列), 只需要检查此两个子region是否还存在引用文件,如果都不存在引用文件就可以认为该父region对应的文件可以被删除。现在再来看看上文中父目录在meta表中的信息,就大概可以理解为什么会存储这些信息了:

    META存储的分裂信息

    生产环境

    【禁用自动切分region,改用手动切分】

    上面说的都是自动切分来实现的负载均衡。建议在生产环境中禁用自动的split(或者将Region设置的大一点),然后手动切割region,可以在晚上或者业务不忙(例如没有大量写操作)的时候手动执行split。

    执行split操作后,Hbase内部的逻辑是:

    第一轮split,遍历所有region的信息,如果region size大于某值(比如4G)则split该region;

    如果一轮后没有大于该值的region则结束,如果还有大于该值的region则继续新一轮split,直到没有region大于该阈值为止。

    如何判断split已完成:检查hdfs上老的region目录是否已被清除来判断split是否已完成。

    Region 合并

    意义

    • 当存在大量没有数据的region时,执行region的合并来避免region过多
    • 之所以会存在大量没有数据的region是因为为了避免region到达阀值引起分裂的开销,创建表格时先进行预分区。

    步骤

    1. 客户端发送指令给Master
    2. Master收到指令后将要合并的region移动到指定的RegionServer
    3. Master发送Merge请求给指定的RegionServer执行合并操作
    4. 最后将被合并的regions从hbase:meta中删除并添加合并后的region

    相关文章

      网友评论

        本文标题:深入理解HBASE(3.3)RegionServer-Regio

        本文链接:https://www.haomeiwen.com/subject/xagyvqtx.html