客户端高阶API用法
过滤器
略
协处理器
用来实现存储过程功能的终端程序(EndPoint)和用来实现触发器功能的观察者(Observers)
协处理器家族的关系如下图所示:
观察者(Observers):
- RegionObserver:针对Region的观察者,可以监听关于Region的操作
- RegionServerObserver:针对RegionServer的观察者,可以监听整个RegionServer的操作
- MasterObserver:针对Master的观察者,可以监听Master进行的DDL操作
- WALObserver:针对WAL的观察者,可以监听WAL的所有读写操作。
- BulkLoadObserver:BulkLoad是采用MapReduce将大量数据快速地导入HBase的一种方式。BulkLoadObserver可以监听BulkLoad行为
- EndpointObserver:可以监听Endpoint的执行过程。
在此我并没有列出这些接口的所有基本实现类,只列出最常用的两种基本实现类:
- BaseRegionObserver:实现了RegionObserver接口的所有需要实现的方法,并给出了 最简单的实现
- BaseMasterObserver:实现了MasterObserver接口的所有需要实现的方法,并给出了最简单的实现
终端程序(EndPoint):
只有一个接口CoprocessorService,并且没有提供基本的实现类。该接口只有一个方法需要实现:getService,该方法需要返回ProtocolBuffers的Service实例。
性能优化
JVM调优
调大堆内存
Hbase 默认的最大RegionServer内存为1GB,而Memstore默认是40%,可以修改$HBASE_HOME/conf/hbase-env.sh
export HBASE_HEAPSIZE=8G
这个参数会影响所有HBase实例,包括Master和Region。这样的话Master和RegionServer都会占用8GB,也可以单独设置Master和RegionServer的大小。
export HBASE_MASTER_OPTS="$HBASE_MASTER_OPTS" -Xms 4g -Xmx 4g"
export HBASE_REGIONSERVER_OPTS="$HBASE_REGIONSERVER_OPTS" -Xms 8g -Xmx 8g"
如何设置内存:
如果同时运行MapReduce的话,RegionServer将是除了MapReduce以外使用内存最大的服务。如果没有MapReduce的话,RegionServer可以调整到大概一半的服务器内存
防止Full GC
发生full GC的原因:
- 同步模式失败(concurrent mode failure):在CMS还没有把垃圾收集完的时候空间还没有完全释放,而这个时候如果新生代的对象过快地转化为老生代的对象时发现老生代的可用空间不够了。解决方法:设置-
XX:CMSInitiatingOccupancyFraction=N来缓解,设置的越小,JVM越早启动垃圾回收进程,一般设置为70。 - 由于碎片化造成的失败(Promotion Failure due to Fragmentation):当前要从新生代提升到老年代的对象比老年代的所
有可以使用的连续的内存空间都大
full GC会造成zookeeper认为RS假死,从而造成朱丽叶暂停。
垃圾回收策略选择:
- 如果你的RegionServer内存小于4GB,就不需要考虑G1GC策略了,直接用-XX:+UseParNewGC-XX:+UseConcMarkSweepGC。
- 如果你的RegionServer内存大于32GB,建议使用G1GC策略
Memstore的专属JVM策略MSLAB
上文所述,为防止内存碎片化,JVM有一个基于线程的解决方案,叫TLAB(Thread-Local allocation buffer)。当你使用TLAB的时候,每一个线程都会分配一个固定大小的内存空间,专门给这个线程使用,当线程用完这个空间后再新申请的空间还是这么大,这样下来就不会出现。特别小的碎片空间,基本所有的对象都可以有地方放。缺点就是无论你的线程里面有没有对象都需要占用这么大的内存,其中有很大一部分空间是闲置的,内存空间利用率会降低。
但是HBase不能直接使用这个方案,因为在HBase中多个Region是被一个线程管理的,多个Memstore占用的空间还是无法合理地分开。于是HBase就自己实现了一套以Memstore为最小单元的内存管理机制,称为MSLAB(Memstore-Local Allocation Buffers)。
MSLAB具体实现如下:
- 引入chunk的概念,所谓的chunk就是一块内存,大小默认为2MB。
- RegionServer中维护着一个全局的MemStoreChunkPool实例,从名字很容看出,是一个chunk池。
- 每个MemStore实例里面有一个MemStoreLAB实例。
- 当MemStore接收到KeyValue数据的时候先从ChunkPool中申请一个chunk,然后放到这个chunk里面。
- 如果这个chunk放满了,就新申请一个chunk。
- 如果MemStore因为刷写而释放内存,则按chunk来清空内存。
跟MSLAB相关的参数是:
- hbase.hregion.memstore.mslab.enabled:设置为true,即打开MSLAB,默认为true。
- hbase.hregion.memstore.mslab.chunksize:每个chunk的大小,默认为2048 * 1024 即2MB。
- hbase.hregion.memstore.mslab.max.allocation:能放入chunk的最大单元格大小,默认为256KB,已经很大了。
- hbase.hregion.memstore.chunkpool.maxsize:在整个memstore可以占用的堆内存中,chunkPool占用的比例。该值为一个百分比,取值范围为0.0~1.0。默认值为0.0。
- hbase.hregion.memstore.chunkpool.initialsize:该值代表了预分配的chunk占总的chunkPool的比例。该值为一个百分比,取值范围为0.0~1.0,默认值为0.0。
Region的自动拆分
Region的拆分分为自动拆分和手动拆分。自动拆分可以采用不同的策略。
ConstantSizeRegionSplitPolicy
从名字上就可以看出这个策略就是按照固定大小来拆分Region。
hbase.hregion.max.filesize: region最大大小,默认值10G
IncreasingToUpperBoundRegionSplitPolicy(默认)
这种策略从名字上就可以看出是限制不断增长的文件尺寸的策略。
默认尺寸:256MB,2048MB,6912MB,10GB
KeyPrefixRegionSplitPolicy
我们还可以自己定义拆分点。KeyPrefixRegionSplitPolicy是IncreasingToUpperBoundRegionSplitPolicy的子类,在前者的基础上
增加了对拆分点(splitPoint,拆分点就是Region被拆分处的rowkey)的定义。它保证了有相同前缀的rowkey不会被拆分到两个不同的Region里面。
该策略会根据KeyPrefixRegionSplitPolicy.prefix_length所定义的长度来截取rowkey作为分组的依据。
所以这个策略适用的场景是:
- 数据有多种前缀。