这里的参数调优,一般来说是针对memStore的flush过程进行调优
Memstore级别限制:Region中任意一个MemStore的大小达到了上限,会触发flush操作
Region级别限制:当一个Region里面的全部memStore占用的内存大小超过阈值的时候会触发一次flush操作(一个Region对应多个Store,一个Store对应一个memStore,因此一个Region里面会有多个memStore)
涉及到的参数有:
默认值是128M,单位是字节,单个memStore占用内存超过这个参数的值将被flush到storeFile
默认值为4,这个参数主要用来和hbase.hregion.memstore.flush.size相乘,如果memstore的内存大小大于这两个参数相乘的结果,比如 128 * 4 M,则会阻塞memstore的写操作,直到降至该值以下
注:上面主要涉及了两个参数,hbase.hregion.memstore.flush.size为128M,一旦memStore里面的数据达到128M,那么就会触发flush操作。但是有一种情况,那就是写入memStore的速度太快,快到memStore达到128M后,还没来得及把这128M写完,就达到了128*4M,这样就会触发阻塞状态,此时Store会拒绝所有写请求,也就是不能再往memStore中写入数据,直到将memStore里面的全部数据都flush到storeFile里面为止。
因此,如果写操作非常频繁的话,可以考虑调大hbase.hregion.memstore.block.multiplier的值,让触发Store阻塞的值变大。
但是也不能过大,因为太大可能会导致一个RegionServer里面的memStore占用内存总和超过hbase.regionserver.global.memstore.size,进而导致全部的memStore阻塞写操作。
这里指的是一个RegionServer里面的全部memStore的占用内存,加在一起超过了阈值,这个阈值一般是RegionServer全部内存的40%。一旦超过了阈值,那么当前RegionServer的全部写操作都会被阻塞。
注意:这里说的是一个RegionServer里面的全部memStore的内存相加超过阈值(RegionServer级别限制),而上一个情况是一个Region里面的全部memStore占用内存达到阈值
这里涉及到了两个参数,分别是hbase.regionserver.global.memstore.size和hbase.regionserver.global.memstore.size.lower.limit
默认值为0.4,是RegionServer中所有memstore占用内存在总内存中的比例,当达到该值,则会从整个RegionServer里面找到占用内存最大的memStore,让其进行flush操作,直到总内存比例降至这个参数的阈值以下,并且在低于阈值之前,阻塞memstore的所有写操作
注:如果写操作频繁,就可以提高当前参数memstore.size的值,避免频繁的触发flush过程。但是这个数值不能设定的过高,因为在RegionServer中还有一个block cache在占用内存。block cache的作用是存储会被频繁访问的数据,提高了数据查询的效率,占用的内存空间比例默认也是0.4
memStore对应写操作,block cache对应读操作。
因此写操作频繁的时候就应该提高memStore的内存,降低block cache的内存
读操作频繁的时候就应该提高block cache的内存,降低memstore的内存
默认值0.95,相当于上一个参数的0.95
如果有 16G 堆内存,默认情况下:
# 达到该值会触发刷写
16 * 0.4 * 0.95 = 6.08
# 达到该值会触发阻塞
16 * 0.4 = 6.4
注:上一个参数介绍里面有说,当一个RegionServer里面全部的memStore内存加一起,占到当前RegionServer内存的40%,就会触发flush操作,并且阻塞所有的memStore的写操作。但这样做有些不合理,在达到阈值前应该给一个缓冲的余地,避免直接进入阻塞状态。
这就是当前这个参数的作用,这个参数设置了一个比例,默认为0.95,假设一个RegionServer的内存总共有16G,那么触发memStore的flush的阈值为16*0.4,而这个参数就会在此基础上再乘0.95,得出的值为6.08G,当全部的memStore占用内存达到这个数值时,就会开始flush操作,并且不会阻塞。如果在原先的阈值16 * 0.4=6.4G之前flush完成,则不会阻塞,如果没有完成就会进入阻塞状态。
注2:因此如果写操作很频繁的话,就可以将当前参数lower.limit的值调小,这样就会提前触发flush过程,留下的缓冲空间更多,尽量避免阻塞。
假设单个memStore的占用内存没有达到内存,而一个RegionServer里面全部的memStore加一起内存也没有达到阈值,正常来说不会触发flush操作,但这里又多了一个新的情况,那就是HLog。当HLog的数量过多时,同样会触发memStore的flush操作,因为HLog的数量太多会影响容灾后的数据恢复效率,而当memStore里面的数据都flush到磁盘后,HLog会被清空。
这里涉及到的参数是hbase.regionserver.maxlogs,含义是HLog文件的最大数量,超过这个数量则触发flush操作。这个参数的值如果给定,那么就是给定的值,如果没有给定,那么就是max(32, hbase_heapsize * hbase.regionserver.global.memstore.size * 2 / logRollSize),从两个值里面选一个最大值。max()里面的第二个参数是根据当前的内存情况计算出的HLog文件数量的最大值
不止HLog数量过多会触发,当HLog文件占用的内存空间达到阈值时,也会触发memStore的flush操作。需要注意的是,如果增大了memStore的内存,那么也要增大HLog文件的内存占用阈值,否则HLog文件达到阈值直接触发flush,而memStore还远没有达到阈值,这样增大memStroe的内存就没有意义了。
定期自动刷写就是启动一个专门的线程,每隔一个固定的时间,就去查看RegionServer里面的Region距离上次flush操作过去的时间,如果达到hbase.regionserver.optionalcacheflushinterval参数的值,还没有flush,就会触发一次flush刷写操作,这个参数的值一般是一个小时。
另外考虑到可能会有多个memStore同时达到了一小时的时间阈值,都需要进行flush操作,为了避免同时进行,导致资源被大量占用。定期自动刷写策略里面有一个延迟机制,memStore不会立刻开始flush,而是随机等待0到5分钟之后才会开始flush操作
在HBase中对数据的删除,更新等操作实际上并不会立即执行,而是打上一个标记,像这种操作很频繁时,同样会触发flush操作,这样数据写入storeFile里面,会触发合并,合并操作时会真正对数据进行删除,更新。
手动执行flush命令,指定某张表的某个region里面的memStore进行flush刷写操作
常见的 put、delete、append、incr、调用 flush 命令、Region 分裂、Region Merge、bulkLoad HFiles 以及给表做快照操作都会对上面的相关条件做检查,以便判断要不要做刷写操作。
注:前面说过触发memStore的flush操作的时机,只要满足了上面的那些条件就会触发flush操作。这里说的是触发了flush操作后,具体哪些memStore会执行flush过程,具体执行的策略
这种刷写策略与HBase1.1之前的策略一样,都是不去区分具体哪个memStore执行flush操作,只要触发了flush操作,就是把当前Region里面的全部memStore都进行flush操作
当满足了flush操作条件后,根据这个策略,会先判断Region里面的每个memStore的使用内存是否超过了某个bound阈值,如果超过了则进行flush刷写操作,如果没有则不会进行flush刷写操作
但是如果触发了flush操作,也就是满足了之前说的时机条件里面的任何一条,却发现Region里面的所有memStore都没有超过bound阈值,此时当前策略就会退化为FlushAllStoresPolicy,即对region里面的全部memStore进行flush过程。
这个bound阈值的计算涉及两个参数:
触发flush过程后,如果memStore超过42M,则只对超过的memStore进行flush操作。如果都没有超过,则对全部的memStore进行flush操作
这里按照isSloppyMemStore的值将memStore分成了两个部分,分别放在sloppyStores 与 regularStores这两个HahsSet里面
当触发了flush过程后
先到regularStores里面判断是否有超过相关阈值的memStore,如果有就对其进行flush过程,其余没有超过阈值的memStore不会被处理。
如果regularStores里面的memStore都没有超过阈值,则到sloppyStores 查找有没有超过相关阈值的memStore,如果有则对其进行flush操作,其余的不做处理
如果上面两个部分都没有找到超过相关阈值的memStore,那么当前策略会退化成 FlushAllStoresPolicy策略,即对region里面的全部memStore进行flush过程
注:这里的isSloppyMemStore
如果相关列簇的hbase.hregion.compacting.memstore.type 参数的值不是 NONE,那么这个 MemStore 的 isSloppyMemStore 值就是 true,否则就是 false。