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進行相關的協調控制;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章