HBase深入分析之RegionServer

HBase深入分析之RegionServer

所有的用户数据以及元数据的请求,在经过Region的定位,最终会落在RegionServer上,并由RegionServer实现数据的读写操作。本小节将重点介绍RegionServer的代码结构和功能,从实现细节上深入理解RegionServer对于数据的操作流程。

1 RegionServer概述

RegionServer是HBase集群运行在每个工作节点上的服务。它是整个HBase系统的关键所在,一方面它维护了Region的状态提供了对于Region的管理和服务;另一方面,它与Master交互,上传Region的负载信息上传,参与Master的分布式协调管理。具体如图(1)所示。

图(1) RegionServer的整体功能图

HRegionServer与HMaster以及Client之间采用RPC协议进行通信。HRegionServer向HMaster定期汇报节点的负载状况,包括RS内存使用状态、在线状态的Region等信息,在该过程中RS扮演了RPC客户端的角色,而HMaster扮演了RPC服务器端的角色。RS内置的RpcServer实现了数据更新、读取、删除的操作,以及Region涉及到Flush、Compaction、Open、Close、Load文件等功能性操作。此时,RS扮演了RPC服务的服务端的角色。RS与Client之间的RPC是HBase最为核心的操作,其服务状况的好坏,直接反映了RS内部、以及它所依赖的HDFS服务质量的好坏,因此,该过程的RPC经常成为分析读写性能异常的突破口。

从RegionServer实现的功能上而言,除了与HMaster和Client之间的RPC通信之外,还包括如下几个重要的模块:

(1)依托ZookeeperWatcher进行的分布式信息共享与任务协调的工作。

MasterAddressTracker:捕获Master服务节点的变化。

HBase使用多Master来解决Master单点故障的问题,主Master服务故障时,它与ZooKeeper的心跳延迟超过阈值,ZooKeeeper路径下的数据被清理,备Master上的ActiveMaserManager服务会竞争该Master路径,成为主Master。

MasterAddresTracker是RS内部监听Master节点变化的追踪器。

([yù zhí]阈值,阈值又叫临界值,是指一个效应能够产生的最低值或最高值。阈值又称阈强度,是指释放一个行为反应所需要的最小刺激强度。低于阈值的刺激不能导致行为释放。)

ClusterStatusTracker:HBase集群状态追踪器。

该选项可以标识当前集群的状态,及它的启动时间。

该设置选项有利于集群中的各个工作节点(RS)统一执行启动和退出操作。

CatalogTracker:跟踪-ROOT-、.META.表的Region的状态。在HBase支持的-ROOT-、.META.、以及User Region三层树级目录结构中,-ROOT-、.META.表用来定位Region的位置,追踪-ROOT-表和.META.表对应Region的变化,可以时刻保证整个层次目录树的完整性。

SplitLogWorker:基于Region的HLog文件切分器。在RS宕机之后,RS上的保存的HLog文件,需要按照Region进行切分。HMaster会把这些文件作为任务放置到Zookeeper的splitlog路径下,RS上SplitLogWorker会尝试获取任务,对获取到的HLog文件按照Region进行分组,处理的结果保存到相应Region的recovered.edits目录下。

(2)Region的管理。

Region是HBase数据存储和管理的基本单位。Client从.META.表的查找RowKey对应的Region的位置,每个Region只能被一个RS提供服务,RS可以同时服务多个Region,来自不同RS上的Region组合成表格的整体逻辑视图。

图(1) RegionServer的整体功能图

RS内涉及到提供的有关Region维护的服务组件有:

1) MemStoreFlusher,控制RS的内存使用,有选择性地将Region的MemStore数据写入文件。该组件可以有效地控制RS的内存使用,flush文件的速度在一定程度上可以反应HBase写服务的繁忙状况。

2) CompactSplitThread,合并文件清理不需要的数据,控制Region的规模。在Store内的文件个数超过阈值时,触发Compact合并文件操作,一是清理被删除的数据,二是多余版本的清理。在Region内的Store文件大小超过阈值,会触发Region的Split操作,一个Region被切分成两个Region。这两个操作都是在CompactSplitThread的各自的线程池中被触发。

3) CompactionChecker,周期性检查RS上的Region是否需要进行Compaction操作,确认需要进行Compaction操作的Region,提交给CompactSplitThread执行请求。

RS的内存的使用分为MemStore和BlockCache。其中MemStore提供写操作的缓存,而BlockCache是提供的读请求缓存。它们详细的内容会在后续章节中介绍。

(3)WAL的管理。

HBase对于数据的更新和删除操作默认先Append到HLog文件,然后再更新到RS对应的Region上,因此,由HLog文件在RS的处理方式,被称为Write-Ahead-Log。多个Region的更新删除操作会被相继写入同一个文件,出于以下的原因,HLog文件会被截断,然后创建新HLog文件继续当前的Append操作。

1) Append操作失败,避免因底层文件系统的文件异常,阻塞数据的操作。

2) 降低存储空间的开销。当HLog上记录的数据完全从MemStore写入HDFS,此时如果多个HLog文件,有利于筛选冗余的HLog文件,提高存储空间的效率。

3) 提高分布式HLog文件切分操作(Distributed Log Split)的效率。多个HLog文件就对应同样数目的LogSplit子任务,从而可以借助多个RS的SplitLogWorker组件快速完成HLog文件的切分,尽快恢复Region的服务。

在RS内,LogRoller定期刷新出一个新的HLog文件。

(4)Metrics

Metrics对外提供了衡量HBase内部服务状况的参数。RegionServer内Metrics包含了内存使用、Region服务状况、Compaction、blockCache等一系列标识服务状况的参数。HBase Metrics继承Hadoop Metrics的实现,目前支持文件、Ganglia、以及数据流等多种输出方式,可以针对输出的Metrics信息灵活构建监控系统

(5)HttpServer

RS内置了一个Jetty Web Server,用来对外提供RS的访问页面。访问页面目前支持实时Metrics信息查询、日志查询、线程的Dump、修改日志级别等操作。

2 RegionServer的启动过程分析

RegionServer服务由org.apache.hadoop.hbase.regionserver.HRegionServer类提供。该类实现了四个接口,分别是HRegionInterface,RegionServerServices,HBaseRPCErrorHandler和Runnable。其中,

HRegionInterface定义了RS对外提供的RPC访问接口,通过RPCServer内置的Handler来处理请求;

RegionServerServices定义了基于RS内部的服务信息接口,例如onlineRegions增、删、查接口,以及获取HLog、文件系统等接口;

HBaseRPCErrorHandler定义了RPCServer异常状态检测处理接口;

Runnable是Java库中的线程接口,实现该接口意味着RegionServer生命周期会运行在run()的函数体内。

RegionServer是一个独立的服务,有一个main函数在启动时被调用,main函数内通过HRegionServerCommandLine的反射机制在JVM内动态加载RegionServer实现类,并按照args解析参数情况,决定启动或者关闭RS服务。

?View CodeJAVA

publicclassHRegionServerimplementsHRegionInterface,HBaseRPCErrorHandler,Runnable,RegionServerServices{...//成员变量定义和成员函数实现publicstaticvoidmain(String[]args)throwsException{...Configurationconf=HBaseConfiguration.create();@SuppressWarnings("unchecked")ClassregionServerClass=(Class)conf.getClass(HConstants.REGION_SERVER_IMPL, HRegionServer.class);//获取RegionServer对应的类newHRegionServerCommandLine(regionServerClass).doMain(args);//创建RegionServer实例并启动}...}

初始化与执行过程包括:

(1)构造HRegionServer实例,初始化变量和对象。这涉及到以下重要变量初始化:

protected volatile boolean stopped = false;//关闭Server的标识,关闭过程中会置成ture

private boolean stopping = false;//关闭Region过程的标识,是进入stopped之前的状态

protected volatile boolean fsOk;//文件系统状态标识,false表示文件系统不可用

private final ConcurrentSkipListMap regionsInTransitionInRS =

new ConcurrentSkipListMap(Bytes.BYTES_COMPARATOR);//RS内处于迁移过程中的Region,其中true表示在open,false表示在close

protected final Map onlineRegions =

new ConcurrentHashMap();//RS内正在服务的Region

protected final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();//修改onlineRegions对象的读写锁

protected final int threadWakeFrequency;//工作线程服务周期间隔

private final int msgInterval;//向Master汇报心跳,收集Metrics间隔

private final long maxScannerResultSize;//Scanner执行next返回的数据量阈值,默认设置是Long.MAX_VALUE

private int webuiport = -1;//webServer的端口号

private final long startcode;//HRegiongServer初始化的时间,取自系统时间

private ServerName serverNameFromMasterPOV;//标识Server的名字

private final int rpcTimeout;//定义到HMaster之间的rpc超时时间

在RS上重要的对象列表,如表1所示。

表1RegionServer重要对象的解释

对象名对应类名功能描述

(2)监听服务组件的初始化与执行。

这个过程初始化以ZooKeeperWatcher为基础的服务,例如监听Master服务节点的MasterAddressManager,标识HBase集群状态的ClusterStatusTracker,以及元数据(-ROOT-, .META.)变化的监听器。启动这些服务可以保证整个集群信息协调一致。

(3)RS服务组件的初始化与执行。

这个过程是初始化compactSplitThread,cacheFlusher,compactionChecker,以及Leases。

(4)尝试连接HMaster,注册RS到HMaster。

(5)周期性收集Metrics和向Master发送心跳。

3 Store相关

Region是RS上的基本数据服务单位,用户表格由1个或者多个Region组成,根据Table的Schema定义,在Region内每个ColumnFamily的数据组成一个Store。每个Store内包括一个MemStore和若干个StoreFile(HFile)组成。如图(3)所示。本小节将介绍Store内的MemStore、StoreFile(HFile)的内部结构与实现。

图(3) Region-Store结构图

3.1 MemStore原理与实现分析

MemStore是一个内存区域,用以缓存Store内最近一批数据的更新操作。对于Region指定的ColumnFamily下的更新操作(Put、Delete),首先根据是否写WriteAheadLog,决定是否append到HLog文件,然后更新到Store的MemStore中。显然,MemStore的容量不会一直增长下去,因此,在每次执行更新操作时,都会判断RS上所有的MemStore的内存容量是否超过阈值,如果超过阈值,通过一定的算法,选择Region上的MemStore上的数据Flush到文件系统。更详细的处理流程图如图(4)。

图(4) 更新操作的流程图

MemStore类内的重要的成员变量:

?View CodeJAVA

volatileKeyValueSkipListSet kvset;//内存中存放更新的KV的数据结构volatileKeyValueSkipListSet snapshot;//Flush操作时的KV暂存区域finalReentrantReadWriteLock lock=newReentrantReadWriteLock();//Flush操作与kvset之间的可重入读写锁finalAtomicLong size;//跟踪记录MemStore的占用的Heap内存大小TimeRangeTracker timeRangeTracker;//跟踪记录kvset的最小和最大时间戳TimeRangeTracker snapshotTimeRangeTracker;//跟踪记录snapshot的最小和最大时间戳MemStoreLAB allocator;//实际内存分配器

注意:

KeyValueSkipListSet是对于jdk提供的ConcurrentSkipListMap的封装,Map结构是的形式。Concurrent表示线程安全。SkipList是一种可以代替平衡树的数据结构,默认是按照Key值升序的。对于ConcurrentSkipListMap的操作的时间复杂度平均在O(logn),设置KeyValue.

KVComparator比较KeyValue中Key的顺序。

写入MemStore中的KV,被记录在kvset中。根据JVM内存的垃圾回收策略,在如下条件会触发Full GC。

 内存满或者触发阈值。

 内存碎片过多,造成新的分配找不到合适的内存空间。

RS上服务多个Region,如果不对KV的分配空间进行控制的话,由于访问的无序性以及KV长度的不同,每个Region上的KV会无规律地分散在内存上。Region执行了MemStore的Flush操作,再经过JVM GC之后就会出现零散的内存碎片现象,而进一步数据大量写入,就会触发Full-GC。图(5)显示这种假设场景的内存分配过程。

图(5) 无处理状态下MemStore内存分配图

为了解决因为内存碎片造成的Full-GC的现象,RegionServer引入了MSLAB(HBASE-3455)。MSLAB全称是MemStore-Local Allocation Buffers。它通过预先分配连续的内存块,把零散的内存申请合并,有效改善了过多内存碎片导致的Full GC问题。

MSLAB的工作原理如下:

 在MemStore初始化时,创建MemStoreLAB对象allocator。

 创建一个2M大小的Chunk数组,偏移量起始设置为0。Chunk的大小可以通过参数hbase.hregion.memstore.mslab.chunksize调整。

 当MemStore有KeyValue加入时,maybeCloneWithAllocator(KeyValue)函数调用allocator为其查找KeyValue.getBuffer()大小的空间,若KeyValue的大小低于默认的256K,会尝试在当前Chunk下查找空间,如果空间不够,MemStoreLAB重新申请新的Chunk。选中Chunk之后,会修改offset=原偏移量+KeyValue.getBuffer().length。chunk内控制每个KeyValue大小由hbase.hregion.memstore.mslab.max.allocation配置。

 空间检查通过的KeyValue,会拷贝到Chunk的数据块中。此时,原KeyValue由于不再被MemStore引用,会在接下来的JVM的Minor GC被清理。

注意:

设置chunk的默认大小以及对于KeyValue大小控制的原因在于,MSLAB虽然会降低内存碎片造成的Full-GC的风险,但是它的使用会降低内存的利用率。如果超过一定大小的KeyValue,此时该KeyValue空间被回收之后,碎片现象不明显。因此,MSLAB只解决小KV的聚合。

MSLAB解决了因为碎片造成Full GC的问题,然而在MemStore被Flush到文件系统时,没有reference的chunk,需要GC来进行回收,因此,在更新操作频繁发生时,会造成较多的Young GC。

针对该问题,HBASE-8163提出了MemStoreChunkPool的解决方案,方案已经被HBase-0.95版本接收。它的实现思路:

 创建chunk池来管理没有被引用的chunk,不再依靠JVM的GC回收。

 当一个chunk没有引用时,会被放入chunk池。

 chunk池设置阈值,如果超过了,则会放弃放入新的chunk到chunk池。

 如果当需要新的chunk时,首先从chunk池中获取。

根据patch的测试显示,配置MemStoreChunkPool之后,YGC降低了40%,写性能有5%的提升。如果是0.95以下版本的用户,可以参考HBASE-8163给出patch。

思考

通过MemStore提供的MSLAB和MemStoreChunkPool给出的解决方案,可以看出在涉及到大规模内存的Java应用中,如何有效地管理内存空间,降低JVM

GC对于系统性能造成的影响,成为了一个研究热点。整体上来说,一是设置与应用相适应的JVM启动参数,打印GC相关的信息,实时监控GC对于服务的影响;二是从应用程序设计层面,尽可能地友好地利用内存,来降低GC的影响。

在ChunkPool就是帮助JVM维护了chunk信息,并把那些已经不再MemStore中的数据的chunk重新投入使用。这样就可以避免大量的YGC。

3.2 MemStore参数控制原理与调优

对于任何一个HBase集群而言,都需要根据应用特点对其系统参数进行配置,以达到更好的使用效果。MemStore作为更新数据的缓存,它的大小及处理方式的调整,会极大地影响到写数据的性能、以及随之而来的Flush、Compaction等功能。这种影响的原因在于以下两个方面。

 RS全局的MemStore的大小与Region规模以及Region写数据频度之间的关系。

 过于频繁的Flush操作对于读数据的影响。

这其中涉及到的可调整的参数如下表。

表MemStore相关的配置参数

参数名称参数含义默认值

hbase.regionserver.global.memstore.upperLimitRS内所有MemStore的总和的上限/Heap Size的比例,超过该值,阻塞update,强制执行Flush操作。0.4

hbase.regionserver.global.memstore.lowerLimit执行Flush操作释放内存空间,需要达到的比例。0.35

hbase.hregion.memstore.flush.size每个MemStore占用空间的最大值,超过该值会执行Flush操作。128MB

hbase.hregion.memstore.block.multiplierHRegion的更新被阻塞的MemStore容量的倍数。2

hbase.hregion.preclose.flush.size关闭Region之前需要执行Flush操作的MemStore容量阈值。5MB

对于上述参数理解:

(1)RS控制内存使用量的稳定。

例如,假设我们的RS的内存设置为10GB,按照以上参数的默认值,RS用以MemStore的上限为4GB,超出之后,会阻塞整个RS的所有Reigon的请求,直到全局的MemStore总量回落到正常范围之内。

以上涉及到cacheFlusher在MemStore总量使用超过上限时,选择Region进行Flush的算法,由MemStoreFlusher.flushOneForGlobalPressure()算法实现。算法的处理流程如下。

关键的数据结构:

?View CodeJAVA

SortedMapregionsBySize=server.getCopyOfOnlineRegionsSortedBySize();//从RS上获取在线的Region,以及它们在MemStore上使用量,并按照MemStore使用量作为Key,降序。SetexcludedRegions=newHashSet();//记录尝试执行Flush操作失败的Region…HRegion bestFlushableRegion=getBiggestMemstoreRegion(regionsBySize, excludedRegions,true);//选出storefile个数不超标、当前MemStore使用量最大的RegionHRegion bestAnyRegion=getBiggestMemstoreRegion(regionsBySize, excludedRegions,false);//选出当前MemStore使用量最大的Region

步骤1:RS上在线的Region,按照当前MemStore的使用量进行排序,并存储在regionsBySize中。

步骤2:选出Region下的Store中的StoreFile的个数未达到hbase.hstore.blockingStoreFiles,并且MemStore使用量最大的Region,存储到bestFlushableRegion。

步骤3:选出Region下的MemStore使用量最大的Region,存储到bestAnyRegion对象。

步骤4:如果bestAnyRegion的memstore使用量超出了bestFlushableRegion的两倍,这从另外一个角度说明,虽然当前bestAnyRegion有超过blockingStoreFiles个数的文件,但是考虑到RS内存的压力,冒着被执行Compaction的风险,也选择这个Region作为regionToFlush,因为收益大。否则,直接选择bestFlushableRegion作为regionToFlush。

步骤5:对regionToFlush执行flush操作。如果操作失败,regionToFlush放入excludedRegions,避免该Region下次再次被选中,然后返回步骤2执行,否则程序退出。

(2)设置两个limit,尽可能减少因为控制内存造成数据更新流程的阻塞。

当RS的MemStore使用总量超过(Heap*hbase.regionserver.global.memstore.lowerLimit)的大小时,同样会向cacheFlusher提交一个Flush请求,并以(1)中Region选择算法,对其进行Flush操作。与(1)不同,这个过程中RS不会阻塞RS的写请求。

因此,在生产环境中,我们肯定不希望更新操作被block,一般会配置(upperLimit –lowerlimit)的值在[0.5,0.75]之间,如果是应用写负载较重,可以设置区间内较大的值。

3.3 StoreFile—HFile

该节请参考:HFile文件格式与HBase读写

3.4 Compaction对于服务的影响

该小节请参考:深入分析HBase Compaction机制

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,214评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,307评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,543评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,221评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,224评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,007评论 1 284
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,313评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,956评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,441评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,925评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,018评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,685评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,234评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,240评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,464评论 1 261
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,467评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,762评论 2 345

推荐阅读更多精彩内容

  • 简介 [HBase]——Hadoop Database的简称,Google BigTable的另一种开源实现方式,...
    高广超阅读 2,337评论 1 27
  • HBase存储架构图 HBase Master 为Region server分配region 负责Region s...
    kimibob阅读 5,564评论 0 52
  • 该文档是用Hbase默认配置文件生成的,文件源是Hbase-default.xml hbase.rootdir 这...
    我是嘻哈大哥阅读 4,742评论 0 7
  • HBase那些事 @(大数据工程学院)[HBase, Hadoop, 优化, HadoopChen, hbase]...
    分痴阅读 3,928评论 3 17
  • 最近在逐步跟进Hbase的相关工作,由于之前对Hbase并不怎么了解,因此系统地学习了下Hbase,为了加深对Hb...
    飞鸿无痕阅读 50,181评论 19 271