1. Hbase 的 sequenceId
1.1. 为什么需要sequenceId
HBase数据在写入的时候首先追加写入HLog,再写入Memstore,也就是说一份数据会以两种不同的形式存在于两个地方。那两个地方的同一份数据需不需要一种机制将两者关联起来?
- Memstore中的数据flush到HDFS文件中后HLog对应的数据是不是就可以被删除了?不然HLog会无限增长!那问题来了,Memstore中被flush到HDFS的数据,如何映射到HLog中的相关日志数据?
- HBase中单个HLog都有固定大小,日志文件最大个数也是固定设置的,。如果日志数量超过这个数量,就必须删除最老的HLog日志。那问题来了,如何知道待删除HLog日志对应的所有数据都已经落盘了?(如果知道哪些数据没有落盘,就可以强制对其执行flush,之后就可以将HLog删除)
- RegionServer宕机之后Memstore中数据必然会丢失,大家都知道可以通过HLog进行恢复。那问题来了,HLog中哪些数据需要恢复?哪些不需要恢复?
这三个问题从本质上来讲是一个问题,都需要一种介质来表示Memstore中数据Flush的那个点对应HLog哪个位置,这个介质就是本文要介绍的重点-sequenceId
。
1.2. HLog日志核心结构
HLog中日志单元WALEntry
表示一次行级更新的最小追加单元,由两部分组成:HLogKey
和WALEdit
.
HLogKey
中包含多个属性信息,包含table name、region name、sequenceid等;WALEdit
用来表示一个事务中的写入/更新集合,一次行级事务可以原子操作同一行中的多个列。
为了保证region级别事务的写入原子性,一次写入操作中所有KeyValue会构成一条WALEdit记录。
1.3. 什么是sequenceid?
sequenceid是region级别一次行级事务的自增序号。需要关注的地方有三个:
- sequenceid是自增序号。很好理解,就是随着时间推移不断自增,不会减小。
- sequenceid是一次行级事务的自增序号。行级事务是什么?简单点说,就是更新一行中的多个列族、多个列,行级事务能够保证这次更新的原子性、一致性、持久性以及设置的隔离性,HBase会为一次行级事务分配一个自增序号。
- sequenceid是region级别的自增序号。每个region都维护属于自己的sequenceid,不同region的sequenceid相互独立。
- 问题一:HLog在什么时候可以过期回收?
- 问题二:HLog数量超过阈值(maxlogs)之后删除最早HLog,应该强制刷新哪些Region?
- 问题三:RegionServer宕机恢复replay日志时哪些WALEntry需要被回放,哪些会被skip?
以上三个问题详见 HBase原理-要弄懂的sequenceId