一、Client-side write buffer 客户端缓存请求
描述:可以缓存客户端的请求,以此来减少RPC的次数,但是缓存只是被存在一个ArrayList中,所以多线程访问时不安全的。
可以使用getWriteBuffer()方法来取得客户端缓存中的数据。 默认关闭。
二、Scan的Caching
描述: next( )方法请求一行就要使用一次RPC,即使你指定了next(int nbRows)也一样,很明显这在性能上会存在一些问题,特别是每次都是请求一个很小的cell的时候。这时候,我们可以考虑在每次RPC的时候,取出更多的row, 这就被称为 scanner caching。这个cache可以在作用在两个层面上:table与scan. 在table层面上, 所有对这table的scan都会激活cache,你也可以只针对某一个scan进行cache。
但是你需要权衡RPC次数与内存使用,假设你把缓存数设置的太高了,就会适得其反。因为每次RPC需要取更多的数据,然后从服务器传到客户端,假设超过了客户端设置的heap最大值,那么就会发生OOM异常。不仅如此,就算没有发生OOM异常,但是由于传输时间长或者客户端处理的时候过长,没有在lease规定的时间内完成,那么就会抛出ScannerTimeoutException。
三、Scan的Batching
描述:之前说到了scan的caching,是针对行级别的,但是有时候row特别长,那cache起来就很有压力了,这个时候,hbase给我们的另一种解决方案是batching, batching是针对列的。它可以控制每次请求next()要取出多少列。当然,就如之前所说,不要batch太多列,会有OOM与ScannerTimeoutException的风险。
显然2和3可以结合起来使用,在减少RPC次数的情况下,也能控制row和column的获取。
四、RowLock
描述:mutate操作,put delete checkAndPut,等等,都会排它的执行,即它们肯定是串行操作的,不会发生并行操作。而get操作是不加锁的,而是使用multiversion concurrency control style来处理,说白了就是读已经存在的最新的记录。
http://en.wikipedia.org/wiki/Multiversion_concurrency_control , 但是要注意一点,假如lease过期了,那么你回来再想使用这个rowlock的时候,就会抛出UnKnownRowLockException。
五、Preflushing on Stop
描述:当某台rs接收到被关闭的要求时,注意这里,是正常的被通知下线,而不是由于什么自身的异常导致的下线,rs会检查所有的memstore,任何大小超过hbase.hregion.preclose.seize配置的memstore会被强制刷新到硬盘(这里指hdfs). 在这个阶段的时候,rs包括region还是正常可以服务的,等到preflush完后,memstore里面剩下的基本上都不多了,只要再执行一次flush就完成了,注意,到后面的那次flush的时候,rs已经不再接收请求了。preflush与其说是提高了region的可用性,不如说是使得rs的关闭更加平滑。
六、region split
描述: 这个是最最基础的问题了,当然,hbase大多数的bug就是出现在这里。当region中的storefile的总大小大于hbase.hregion.max.filesize设置的大小时,这个region就要split,在这个region一分为二的过程中,进行的非常快,因为hbase只需要为两个新的region(在hbase中也成为daughters)建两个reference file而已.当两个daughters准备上可以上线的时候,后台线程会把父region的store files写到两个子region中,同时也会替换掉reference file。最后master会看看到底需不需要做load balance。
七、Compactions
:当region内的storefile的数量大于hbase.hstore.compaction.min(hbase.hstore.compactionThreshold)时,就会触发minor compaction,而每次minor ompaction所包含的最大文件数由hbase.hstore.compaction.max指定。并且,hbase.hstore.compaction.min.size(通常设置成和memstore flush的值一样)与hbase.hstore.compaction.max.size(通常设置为Long.MAX_VALUE)会进一步限制参与compact的文件。与minor compaction不同, major compact会把所有的store里面的文件合成一个大文件,compact的类型在检查阶段就已经确定好了。以下几种情况会触发检查compaction,1、shell中的compact或者major_compact请求 2、memstore flush后 3、请求相应的api中的majorCompact( ) 4、后台线程轮询,时间由hbase.server.thread.wakefrequency和hbase.server.thread.wakefrequency,multiplier相乘所得。假如你在shell中请求了major_compact,或者请求了api中的majorCompact,都会强制执行majorCompact,在其它情况下,rs会依据hbase.hregion.majorcompaction来判断是否应该执行major。
split和compact相对来说复杂点,我找时间再把源码拉出来分析下吧。说到源码,我把源码中compact线程中比较重要的一段注释提一下:
合并storefiles,这可能需要一点时间。在这段时间时间中store还是能够正常提供服务的,它还是能从storefile中取值,也能从memstore中写入新的storefile。直到新的合并完的storefile已经全部写到硬盘了,原来的storefiles才会删掉。