HBase sequenceId知识点略记

在HBase中,sequenceId是实现一致性的灵魂,这里的一致性有两方面意思:

  1. 顺序性,即先写的先被读到,未提交的写不能被读到;
  2. 完整性,包含如下几点;
  • 未持久化到hfile的数据,对应的wal文件不能删除
  • 如果由于wal文件过多需要清理,则需要先把对应的数据持久化
  • 异常恢复过程中,需要能够找出wal文件中尚未持久化的部分

以下从seqId的生成、保存和使用几方面对相关知识点进行了整理;

在哪里生成

1、每个HRegion都对应了一个的MultiVersionConcurrencyControl,该类中有2个变量:readPoint和writePoint,rpcHandler处理写请求的过程中,在写wal之前,会通过将writePoint加1来得到最新的seqId,然后创建1个WriteEntry,封装了该seqId和代表是否完成的状态,最后放入到1个链表中,代码如下:

synchronized (writeQueue) {
  long nextWriteNumber = writePoint.incrementAndGet();
  WriteEntry e = new WriteEntry(nextWriteNumber);
  writeQueue.add(e);
  action.run();
  return e;
}

在哪些地方保存

  1. 写wal,walEntry的key中包含该seqId,同时会更新SequenceIdAccounting中的highestSequenceIds,其中保存了该WAL实例负责的各个region的最大seqId,值得注意的时,如果启用了multiwal,则会存在多个WAL实例并各自对应一个SequenceIdAccounting实例;
  2. 写memstore,cell中包含该seqId;
  3. 写完成时,更新readPoint为该seqId,这里会检查writeQueue中是否存在更小的未完成WriteEntry,如果有,则不会更新;
  4. flush,生成的hfile中,除了会在cell中包含该seqId之外,还会在fileInfo中保存MAX_SEQ_ID,代表hfile中的最大seqId,同时也会更新SequenceIdAccounting中的lowestUnflushedSequenceIds,其中保存了每个region下各个store的最小未持久化seqId;
  5. report,rs每隔3s会上报信息给master,其中包含了每个region及其各个store的lastFlushedSequenceIds;
  6. compact,会获取smallestReadPoint,seqId小于该值的cell会被当前及后续的所有scanner读取,因此在生成的新hfile中这些cell不需要再保存seqId;
  7. roll log,会获取SequenceIdAccounting中的highestSequenceIds,将其保存到AbstractFSWAL中的walFile2Props,然后将highestSequenceIds清空;
  8. bulkload,会先请求执行flush,其中会通过writePoint加1得到最新的seqId,并将其作为后缀放在hfile的文件名中(完整suffix:"_SeqId_" + seqNum + "_");

在哪些地方使用

  1. rpcHandler处理读请求的时候,会获取region的mvcc中最新的readpoint,以此过滤memstore和hfile中的数据;
  2. logRoller创建新wal文件时,会对AbstractFSWAL中的walFile2Props与SequenceIdAccounting中的lowestUnflushedSequenceIds进行比较,如果某个wal文件中各region的数据都已经落盘,则将其转移到oldWALs目录;
  3. log文件过多时,需要将最早那个log文件转移到oldWALs目录,此时也是对AbstractFSWAL中的walFile2Props与SequenceIdAccounting中的lowestUnflushedSequenceIds进行比较,找出存在未落盘数据的reigon进行flush;
  4. rs挂掉后执行scp,需要splitlog,将不同reigon的log放到该reigon的recovered.edits目录下,用来在open时replay,此时splitworker会从master获取seqId来过滤掉确定已落盘的数据,获取到的seqId分为region级别的lastFlushedSequenceId和store级别的storeSequenceId,分别用于读取wal文件和写入recovered.edits目录时进行过滤;
  5. openreigon的时候需要对recovered.edits目录下的数据进行replay,此时会再次根据store中各hfile的最大seqId进行过滤,这里再次过滤的原因是,splitlog时从master获取的seqId是rs定时上报的,存在一定的滞后;
  6. 另外,新引入的serial replication特性,也会使用seqId进行相关的协调控制;
上一篇:phoenix-5.0.0与CDH6.0.1兼容性导致二级索引不可用问题解决


下一篇:HBase2.0 regionServer退出处理流程