RegionServer 会将数据保存在内存中(MemStore),直到满足一定条件,将其 flush 到磁盘上。这样可以避免创建很多小文件。内存存储是不稳定的,常见的也是 HBase 使用的解决方案是 write-ahead logging(WAL)
:每次更新操作都会写日志,并且写日志和更新操作在一个事务中。
WAL 在 HBase 中的使用
HBase WAL处理过程如下:
-
Client 发起一次更新操作,通过RPC调用发送。这些RPC请求会批量的发送到目标 Region 所在的 RegionServer 上。
-
当请求对象到达 RegionServer,会被交给 Region 对应 HRegion 实例处理。数据首先被写到 WAL(HLog),然后被存入 MemStore,这两者都写入成功才会返回 Client 成功。
-
MemStore 持续写入的过程中,满足条件时会写入文件系统,生成 HFile,存储在 HDFS 上的指定路径。
如果 RegionServer 崩溃,MemStore 丢失,WAL可以保证数据不会丢失。其他 RegionServer 可以读到 HDFS 上的 HLog 文件进行恢复操作。
HLog
实现 WAL 的类叫做 HLog,每个 HRegionServer 中都有一个 HLog 对象,当 HRegion 实例化时, HLog 对象会传入 HRegion 的构造器。当 HRegion 接受到一个更新操作,通过 HLog 对象将操作写入 WAL(核心是append()方法),HLog 文件定期会滚动出新的文件,并删除旧的文件(已持久化到 HFile 中的数据)。
根据上文的描述和上面的图示可以看出,多个 Region 使用同一个 HLog,结构如下:
数据按照到达的顺序写入到 WAL 中
HBase WAL
HLog 恢复
当 HRegionServer 意外终止后,HMaster 会感知到,首先会处理遗留的 HLog文件,将其中不同 region 的日志数据进行拆分,分别放到相应 region 的目录下,然后再将失效的 region 重新分配。
接收到这些 region 的新的 HRegionServer 在 Load Region 的过程中,发现有 HLog 需要处理,会通过 Replay 的方式会放 HLog 中的数据到 MemStore 中,然后进行一次 flush,完成数据恢复。
HLogKey 和 WALEdit
WAL 使用的是 Hadoop 的 SequenceFile,按照 key/value 集合的方式存储。HLogKey 记录了每次修改的 sequence number、写入时间、归属 region 和 table,以及集群ID(用于集群间复制) 。WALEdit 封装了每一次修改请求的内容,将原子性的操作写入一个 WALEdit 对象,例如:更新了一行中的10列,对于10列的更新会记录在一个 WALEdit 中,保证一致性。
需要特别注意 sequence number
,起始值为0(或者是最近一次存入文件系统中的 sequence number)。由于在 HBase 中数据被存储在多个地方(HFile、MemStore 和 HLog),需要有一种机制能够确定,HLog 中的哪些数据已经在 HFile 中,哪些数据随着 MemStore 丢失了需要重放,而 sequenceId 就起到这样一个作用。详细参考后续文章。
LogSyncer
Hbase 有两种将WAL保存到磁盘的方式,一种是延迟日志刷写(deferred log flushing),另一种不是。通过setDeferredLogFlush(boolean isDeferredLogFlush),isDeferredLogFlush 的默认值为 false,即默认不延迟日志刷写。
默认每次更新都会调用写日志的 sync() 方法,保证写入日志的更新被文件系统确认,开销是比较大的,但不及时同步可能因为机器宕而丢日志。
Table 如果设置每次不同步,则写操作会被 RegionServe 缓存,并启动一个 LogSyncer 线程来定时同步日志,定时时间默认是1秒,也可由 hbase.regionserver.optionallogflushinterval
设置。
LogRoller
运行于后台的线程,在特定时间间隔内滚动日志,通过 hbase.regionserver.logroll.period
参数设置,默认是一小时。
HLog.rollWriter() 用于滚动日志,HLog.cleanOldLogs() 在其后调用,检查写入到 HFile 的最大的 sequence number(表明小于这个序列号的数据都已经被保存了),然后检查 HLog 中都小于这个数字的文件,移动到 .oldlogs 文件夹中,后续进行清理。
当 HLog 的数量过多,超过 hbase.regionserver.max.logs
设置的阈值,MemStore 会进行一次强制的 flush。
Reference:
《HBase- The Defintive Guide》
网友评论