HBase mem store 刷盘时机
前言
在HBase 读写流程中,我们知道了写入数据的时候会写写入 mem store 这个内存空间。那找到合适的一个刷盘时间就是需要思考的问题。
假如,让你负责这个部分的设计,你会考虑什么刷写条件呢?
-
首先,内存空间肯定不能占用的非常大才去刷盘,而作者又考虑了两个层面的内存占用。
- region 级别的。我们知道每个 region 对应一个或多个store,一个 store 对应一个 mem store。当 region 中的 mem store 大于
hbase.hregion.memstore.flush.size ( 默认 128M )
,会触发当前 region 全部 mem store 刷盘。
在这里就有一个问题了,比如我这个 store 写入的很多,别的 store 写入的很少,那就意味着刷盘的时候会产生小文件,这其实是我们不希望发生的。所以作者建议,我们在使用的时候非必要的话创建一个列族就可以了。
- region server 级别。在这个 JVM 进程中,有多少内存会给写缓存使用呢,其实是靠
hbase.regionserver.global.memstore.size (默认0.4)
参数控制,也就是说给写缓存使用的空间是整个堆内存的 40%。可以容忍的最大的写入内存占用为heap_size * 0.4 * hbase.regionserver.global.memstore.size.lower.limit (默认 0.95)
需要注意的是:
超过这个大小后,RegionServer 的所有写操作将会被阻塞,而且这个阻塞可能会持续到分钟级别 - region 级别的。我们知道每个 region 对应一个或多个store,一个 store 对应一个 mem store。当 region 中的 mem store 大于
-
如果写入的数据量比较小,没有达到上面的触发条件 ,那数据也不可以一直在内存中的,所以,作者提供了定时刷写。
- RegionServer 在启动的时候会启动一个线程 PeriodicMemStoreFlusher 每隔
hbase.server.thread.wakefrequency
时间去检查属于这个 RegionServer 的 Region 有没有超过一定时间都没有刷写,这个时间是由hbase.regionserver.optionalcacheflushinterval
参数控制的,默认是 3600000,也就是1小时会进行一次刷写。如果设定为0,则意味着关闭定时自动刷写。
为了防止一次性有过多的 MemStore 刷写,定期自动刷写会有 0 ~ 5 分钟的延迟,具体参见 PeriodicMemStoreFlusher 类的实现。
- RegionServer 在启动的时候会启动一个线程 PeriodicMemStoreFlusher 每隔
刷盘影响
mem store 会在不同条件下触发刷盘 ,那么数据在整个刷盘的过程中,对 region 的数据写入有什么影响?
在数据开始刷盘到结束的这段时间内,该 region 的访问都是被拒绝的,这是因为在数据刷盘结束时, RS 会对该 region 做一个 snapshot ,同时 HLog 做一个 checkpoint 操作,通知 ZK 那些 HLog 可以被移动到 .logs。从下面的图中,可以看到,在 mem store 写盘开始,相应的 region 会加上 UpdateLock 锁,写盘后释放。
思考
- 刷盘到 store 路径后,需要对这些文件做什么管理(总不能任由文件数随意增长吧)?这就涉及到文件的 compact 及 split。