Region拆分
Region的拆分逻辑是通过CompactSplitThread线程的requestSplit方法来触发的,每当执行MemstoreFlush操作时都会调用该方法进行判断,看是否有必要对目标Region进行拆分。
Region可拆分的前提是需要满足如下约束条件:
-
目标RegionServer的线上Region数没有达到hbase.regionserver.regionSplitLimit参数阀值
该参数的默认值为1000,达到900时RegionServer将会打印警告:Total number of regions is approaching the upper limit。
-
StoreFile文件数量没有达到hbase.hstore.blockingStoreFiles参数阀值
此时会优先触发整理操作(详细参考Region整理章节)
-
要拆分的Region不属于meta表格
HBase不支持对meta表格中的Region做拆分操作。
-
Region没有处于recovering状态(参考Region恢复章节)
-
由具体的拆分策略来做决定,通过其shouldSplit方法
HBase对外提供了5中拆分策略,全部由RegionSplitPolicy派生而来,5中策略分别为:
-
ConstantSizeRegionSplitPolicy
当Region中某个Store数据量达到hbase.hregion.max.filesize参数阀值时进行拆分
-
IncreasingToUpperBoundRegionSplitPolicy
当Region中某个Store数据量达到sizeToCheck阀值时进行拆分,sizeToCheck是通过如下方法计算得出的,如果RegionServer上含有指定Table的Region数量在(0,100]之间,返回如下公式的值:
min(hbase.hregion.max.filesize, regionCount^3 * initialSize)
否则返回hbase.hregion.max.filesize参数值。由此可见该拆分策略是增量式的,随着Region数量的增多,拆分阀值也逐渐越大,直至达到目标上限为止。
-
DelimitedKeyPrefixRegionSplitPolicy
拆分策略如下:如果定义rowkey时,采用'_'作为字段分隔符(如:userid_eventtype_eventid),则采用该策略拆分之后,能够确保具有相同userid的记录隶属于同一Region。
该类继承至IncreasingToUpperBoundRegionSplitPolicy,其拆分前提与父类相同,只是在拆分点的获取上略有不同(参考下一章节)。
-
KeyPrefixRegionSplitPolicy
与DelimitedKeyPrefixRegionSplitPolicy类似,只不过是选取指定长度的字符前缀来作为row的分组。
-
DisabledRegionSplitPolicy
该策略shouldSplit方法永远返回false,表示不启用拆分功能,不对Region做任何拆分。
-
拆分点主要是通过调用拆分策略的getSplitPoint方法来进行获取,不同的拆分策略有着不同的获取逻辑,具体如下:
-
如果拆分点是用过通过split命令强制声明的,返回用户指定的拆分点。
-
如果采用的拆分策略为ConstantSizeRegionSplitPolicy或IncreasingToUpperBoundRegionSplitPolicy,则选取Region中数据总量最大的Store,通过其getSplitPoint方法来获取切分点。
方法在执行过程中还需要考虑StoreFileManager的实现类型:
-
如果是DefaultStoreFileManager
从目标Store中选择一个数据量最大的StoreFile,对其执行getFileSplitPoint方法来获取midkey作为拆分点(从根索引中读取,参考HFile存储结构)。
-
如果是StripeStoreFileManager(采用了StripeCompaction)
如果Store中只有一个Stripe,获取数据量最大的StoreFile,对其执行getFileSplitPoint方法来获取midKey信息作为该Region的拆分点。
如果有多个Stripe,则试图在所有Stripe中间找到如下图所示的分隔线,使分割线左右两侧的数据总量最为接近。
分割线确立以后,如果能满足以下约束条件,便可直接确定该Region的拆分点。
largeSideSize / smallSideSize < 1.5
其中largeSideSize为数据总量偏大的一方(即图中分割线左边的数据总量),smallSideSize为数据总量偏小的一方(即图中分割线右边的数据总量),而1.5是通过hbase.store.stripe.region.split.max.imbalance配置项声明的。
拿示例图片来做说明:由于largeSideSize(3072m)/smallSideSize(2560M)=1.2,数值低于1.5,因此直接将Stripe-2的endRow作为该Region的拆分点。而如果Stripe-2的大小为20480m,那么便没有办法满足以上约束条件,这时需要进行如下处理:
将stripe-2的一半大小划分到右侧区域(即将分割线画到如图所示位置),然后重新生成radio值。
largeSideSize(12800) / smallSideSize(11264) = 1.14
如果新生成的radio值比之前的radio还要大,则放弃这种处理办法,依然采用之前的处理方式,否则从stripe-2中选择数据总量最大的StoreFile,对其执行getFileSplitPoint方法来获取midkey信息,并将其作为该Region的拆分点返回。
-
Region在拆分过程中,需要HMaster和RegionServer的共同参与,中间的协调工作通过Zookeeper来实现。针对每一个待拆分的Region,RegionServer端会创建/hbase/region-intransition/{regionName}拆分节点,节点内容为RegionTransition对象,对象由以下几部分信息构成:
-
eventType
事件类型,这里为RS_ZK_REQUEST_REGION_SPLIT,Master端会对该事件类型进行捕获,并做出相应的回调处理。
-
regionName
表示对哪个Region执行的转换操作。
-
serverName
目标Region部署在哪台RegionServer上。
-
payload
装载额外的信息用于处理目标事件,这里为子Region的HRegionInfo信息。
拆分节点创建成功以后,HMaster端会进行相应的回调处理,通过监听Zookeeper的目标节点路径(参考AssignmentManager类的handleRegion方法)。在回调处理中,首先从目标拆分节点中读取出RegionTransition对象,修改其eventType属性值为RS_ZK_REGION_SPLITTING,并将该对象重新赋予目标拆分节点。随后对参与拆分操作的Region状态进行修改,将待拆分的父Region标记成SPLITTING状态,将两个新生成的子Region标记为SPLITTING_NEW,通过RegionStates类的updateRegionState方法。
与此同时,RegionServer端在创建出拆分节点以后会进入循环等待状态(代码逻辑参考ZKSplitTransactionCoordination类的waitForSplitTransaction方法),直至其eventType属性值变为RS_ZK_REGION_SPLITTING,然后开始执行如下处理:
-
在待拆分Region目录下创建.splits子目录来作为拆分目录。
-
将待拆分的Region关闭,不再提供线上服务,通过HRegion的close方法。
-
对Region中的storeFile进行拆分。
假设将目标Region拆分成Split-A(存储拆分点之前的数据)和Split-B(存储拆分点之后的数据),拆分规则如下:
首先定义如下3个变量:
(1)firstKey:用于表示StoreFile文件的起始key;
(2)lastKey:用于表示StoreFile文件的结束key;
(3)splitKey:用于表示Region的拆分点。
-
如果StoreFile满足firstKey < splitKey < lastKey,将[firstKey,splitKey]区间上的数据赋予Split-A。
-
如果StoreFile满足firstKey < lastKey < splitKey,将整个StoreFile赋予Region-a。
-
如果StoreFile满足splitKey < firstKey < lastKey,将整个StoreFile赋予Region-b
Tip
在HBase中,拆分后的StoreFile子文件是通过Reference来进行描述的,其数据内容采用protobuf进行序列化,每个Reference文件在HDFS上的存储路径为path/to/table/parentRegion/.splits/childRegion/cf/storefile.parentRegion拆分完成以后需要将子Region从path/to/table/parentRegion/.splits/childRegion路径移动到path/to/table/路径下。
-
-
修改meta表中Region元数据信息,通过MetaTableAccessor类的splitRegion方法
将子Region添加到meta表格中,并将父Region标记为splitting状态(新增splitA和splitB列信息,内容为子Region的HRegionInfo)。
-
将拆分后的子Region进行启动,通过HRegion的openHRegion方法
启动后的子Region与父Region部署在同一个RegionServer上,同时由于拆分后的子Region内部含有Reference文件,因此需要对其执行整理操作(参考Region整理章节)。
RegionServer端完成子Region的启动之后,需要将启动结果通知到HMaster端,通知逻辑同样是借助于Zookeeper来实现的,首先从Zookeeper的目标拆分节点中获取RegionTransition对象,将其eventType属性值修改为RS_ZK_REGION_SPLIT。节点状态修改后,Master端会进行如下回调处理:
(1)将父Region标记成SPLIT状态,并对其进行下线处理;
(2)对拆分后的子Region进行上线,将其标记为OPEN状态;
(3)删除Zookeeper中的拆分节点。
至此,Region的拆分逻辑成功执行,子Region开始提供线上服务。
Region在拆分过程中是采用事务进行管理的,如果在拆分的过程中出现了异常,可以对事务进行回滚,从而避免脏数据的产生。事务逻辑主要是通过SplitTransaction类来封装的,该类的使用模版如下:
SplitTransaction st = new SplitTransaction(conf, parent, midKey); if (!st.prepare()) return; try { st.execute(server, services); } catch (IOException ioe) { try { st.rollback(server, services); return; } catch (RuntimeException e) { myAbortable.abort("Failed split, abort"); } }
可以看到回滚逻辑主要通过rollback方法来实现,方法在执行过程中会进行如下处理:
-
首先获取当前Region的拆分进度,以及到达该进度之前都做了哪些工作。
Region在拆分过程中大致会经历如下几个阶段(详细的拆分过程可参考上一章节):
(1)STARTED - 拆分逻辑被触发;
(2)PREPARED - 执行拆分前的准备工作;
(3)BEFORE_PRE_SPLIT_HOOK - 调用协处理器进行拆分前的拦截处理;
(4)AFTER_PRE_SPLIT_HOOK - 协处理器处理结束;
(5)SET_SPLITTING - Zookeeper中创建出拆分节点;
(6)CREATE_SPLIT_DIR - 拆分目录被生成;
(7)CLOSED_PARENT_REGION - 父Region被关闭;
(8)OFFLINED_PARENT - 父Region被下线,不再提供线上服务;
(9)STARTED_REGION_A_CREATION - 第一个子Region被成功创建;
(10)STARTED_REGION_B_CREATION - 第二个子Region被成功创建;
(11)PONR - 回滚分界点,即该阶段之前的操作可以回滚;
(12)OPENED_REGION_A - 第一个子Region被开启;
(13)OPENED_REGION_B - 第二个子Region被开启;
(14)BEFORE_POST_SPLIT_HOOK - 调用协处理器进行拆分后的拦截处理;
(15)AFTER_POST_SPLIT_HOOK - 协处理器处理结束。
每到达一个阶段,HBase都会创建JournalEntry实体来对当前的进度进行标记,并将该实体添加到journal集合中。这样,通过journal集合便可获知当前拆分进度已经进入到了哪个阶段,然后依次向前回溯对每个阶段进行回滚即可。需要注意的是如果拆分进度到达了PONR阶段(point-of-no-return),此时将无法在执行回滚操作,只能将RegionServer停掉以便ServerShutdownHandler对Region的元数据进行修复(参考Region状态管理章节中有关状态修复的介绍)。
针对该情况RegionServer宕掉以后将会打印如下提示信息:
Abort; we got an error after point-of-no-return
-
针对当前进度之前的所有操作进行回滚。
回滚操作是通过不断迭代来完成的,每次回滚都是针对一个具体的阶段来进行。
(1)如果回滚时处于SET_SPLITTING阶段,删除Zookeeper中的拆分节点;
(2)如果回滚时处于CREATE_SPLIT_DIR阶段,清理父Region下的拆分目录;
(3)如果回滚时处于CLOSED_PARENT_REGION阶段,重新对父Region执行初始化操作;
(4)如果回滚时处于STARTED_REGION_A_CREATION阶段,清理第一个子Region的存储目录;
(5)如果回滚时处于STARTED_REGION_B_CREATION阶段,清理第二个子Region的存储目录;
(6)如果回滚时处于OFFLINED_PARENT阶段,重新将父Region上线;
(7)如果回滚时处于PONR或以后的阶段,将RegionServer停掉。
http://blog.csdn.net/javaman_chen/article/details/48048315
相关推荐
当region过大的时候.hbase会拆分region , 这也是Hbase的一个优点 . HBase的region split策略一共有以下几种: 1、ConstantSizeRegionSplitPolicy 0.94版本前默认切分策略 当region大小大于某个阈值(hbase.hregion....
【HBASERegion数量增多问题描述及解决方案】 在HBase分布式数据库中,Region是表数据的基本存储单元,它将表的数据按照ROWKEY的范围进行分割。随着数据的增长,一个Region会分裂成两个,以此来确保数据的均衡分布。...
HBASE的主要原理解读:包括HBase 读写逻辑、HBase region拆分和合并
hbase-region-inspector, HBase区域统计信息的可视化仪表板 hbase-region-inspectorHBase区域统计信息的可视化仪表板。 用法下载与HBase集群版本匹配的可执行二进制插件,添加execute权限,并使用以下命令行参数启动...
- **数据迁移**:原始Region的数据根据splitpoint被拆分为两部分,分别进入新的Region。 - **元数据更新**:HMaster接收到RegionServer的通知,更新meta表中的Region信息,确保客户端能够找到正确的Region。 - **...
hbase-packet-inspector hbase-packet-inspector (HPI)是用于分析HBase RegionServers网络流量的命令行工具。 HPI读取tcpdump文件或捕获网络接口的实时数据包流,以提取有关客户端请求和响应的信息。 您可以对其...
Hbase思维导图之物理模型
1. **Region**:Region是HBase中数据存储和负载均衡的基本单位。一个Region包含了一个或多个连续的行键区间。当一张表的数据量增长时,为了保证性能,表会被水平分割成多个Region。每个Region都会被分配到一个...
4. Coprocessor:在Region服务器端实现业务逻辑,减少网络传输。 六、HBase监控与故障恢复 1. 监控指标:包括内存使用、磁盘I/O、网络流量等,通过JMX和Hadoop Metrics2提供。 2. 故障处理:Master节点和Region...
在HBase这个分布式列式数据库中,Region是其核心的数据存储和管理单元,它负责存储表中的行数据。随着数据量的增长,一个Region可能会变得过大,导致读写性能下降。这时,就需要对Region进行数据切割(Split),以...
HBase中的Region分割(Region Split)是一个关键特性,它允许HBase在表数据量增大时,自动将一个Region分割成两个,从而保证每个Region的大小都保持在一个合理的范围。这是实现HBase高扩展性和高性能的关键机制之一...
如果某个Region过大,可能会导致读写性能下降,因此,它会尝试将大的Region拆分为更小的部分,以提高并发处理能力。 3. **Cluster状态监控**:balancer持续监控整个集群的状态,包括RegionServer的在线情况、资源...
在IT行业中,尤其是在大数据处理领域,HBase是一个广泛使用的分布式、高性能、列式存储的NoSQL数据库。HBase是建立在Hadoop文件系统(HDFS)之上,为处理大规模数据提供了一个高效的数据存储解决方案。而Spring Data...
Hbase思维导图
6. **Region**:Region是表的逻辑分区,每个Region包含一个或多个列族,Region会随着数据的增长自动分裂。 7. **Region Server**:Region Server是HBase的主要工作节点,负责Region的存储和管理,包括读写操作。 8. ...
HBase 元数据修复工具包。 ①修改 jar 包中的application.properties,重点是 zookeeper.address、zookeeper.nodeParent、hdfs.root.dir配置项,hdfs 最好写 ip; ②将core-site.xml、hdfs-site.xml添加到BOOT-INF/...
- **第5章:通过Coprocessors扩展HBase**:Coprocessors是HBase中的一个重要特性,用于在服务器端执行用户定义的逻辑,从而减少网络传输开销并提高性能。本章将详细介绍Coprocessors的工作原理及其应用场景。 - **...
2. **Region服务器通信**:开发包内部实现了与HBase Region服务器的通信协议,使得Java应用可以透明地与分布在全球的数据进行交互。 3. **数据模型**:HBase的数据模型基于行、列族、列和时间戳。Java-HBase开发包...
HBase中的多个HMaster通过Zookeeper的Master Election机制来确定主HMaster,主HMaster负责管理表和Region的生命周期,包括表的创建、删除、分区以及Region的迁移等。 HRegionServer是HBase的核心组件,它们直接处理...