HBase源碼分析之WAL

WAL(Write-Ahead Logging)是數據庫系統中保障原子性和持久性的技術,經過使用WAL能夠將數據的隨機寫入變爲順序寫入,能夠提升數據寫入的性能。在hbase中寫入數據時,會將數據寫入內存同時寫wal日誌,爲防止日誌丟失,日誌是寫在hdfs上的。 
默認是每一個RegionServer有1個WAL,在HBase1.0開始支持多個WALHBASE-5699,這樣能夠提升寫入的吞吐量。配置參數爲hbase.wal.provider=multiwal,支持的值還有defaultProvider和filesystem(這2個是一樣的實現)。 
WAL的持久化的級別有以下幾種:數據庫

  1. SKIP_WAL:不寫wal日誌,這種能夠較大提升寫入的性能,可是會存在數據丟失的危險,只有在大批量寫入的時候才使用(出錯了能夠從新運行),其餘狀況不建議使用。
  2. ASYNC_WAL:異步寫入
  3. SYNC_WAL:同步寫入wal日誌文件,保證數據寫入了DataNode節點。
  4. FSYNC_WAL: 目前不支持了,表現是與SYNC_WAL是一致的
  5. USE_DEFAULT: 若是沒有指定持久化級別,則默認爲USE_DEFAULT, 這個爲使用HBase全局默認級別(SYNC_WAL)

wal寫入

先看看wal寫入中的幾個主要的類 
1. WALKey:wal日誌的key,包括regionName:日誌所屬的region 
tablename:日誌所屬的表,writeTime:日誌寫入時間,clusterIds:cluster的id,在數據複製的時候會用到。 
2.WALEdit:在hbase的事務日誌中記錄一系列的修改的一條事務日誌。另外WALEdit實現了Writable接口,可用於序列化處理。 
3. FSHLog: WAL的實現類,負責將數據寫入文件系統 
在每一個wal的寫入這裏使用的是多生產者單消費者的模式,這裏使用到了disruptor框架,將WALKey和WALEdit信息封裝爲FSWALEntry,而後經過RingBufferTruck放入RingBuffer中。接下來看hlog的寫入流程,分爲如下3步:apache

  1. 日誌寫入緩存:由rpcHandler將日誌信息寫入緩存ringBuffer.
  2. 緩存數據寫入文件系統:每一個FSHLog有一個線程負責將數據寫入文件系統(HDFS)
  3. 數據同步:若是操做的持久化級別爲(SYNC_WAL或者USE_DEFAULT 則需進行數據同步處理

下面來詳細說明一下各種線程是如何配合來實現這幾步操做的,數組

  1. rpcHandler線程負責將日誌信息(FSWALEntry)寫入緩存RingBbuffer,在操做日誌寫完後,rpcHandler會調用wal的sync方法,進行數據同步,其實際處理爲寫入一個SyncFuture到RingBuffer,而後blocking一直到syncFuture處理完成。
  2. wal線程從緩存RingBuffer中取數據,若是爲日誌(FSWALEntry)就調用Writer將數據寫入文件系統,若是爲SyncFuture,則由專門的同步線程來進行同步處理。 
    總體處理流程圖以下: 
    這裏寫圖片描述

HLog的寫入

wal寫入文件系統是經過Writer來寫入的,其實際類爲ProtobufLogWriter,使用的是Protobuf的格式持久化處理。使用Protobuf格式有以下優點:緩存

  1. 性能較高
  2. 結構更加緊湊,節省空間
  3. 方便擴展以及支持其餘語言,經過其餘語言來解析日誌。框架

    寫入的日誌中是按WALKey和WALEdit來依次存儲的(具體內容見前面WALKey和WALEdit類的說明),另外還將WALKey和WALEdit分別進行了壓縮處理。異步

wal同步過程

每一個wal中有一個RingBufferEventHandler對象,其中用數組管理着多個SyncRunner線程(由參數hbase.regionserver.hlog.syncer.count配置,默認5)來進行同步處理,每一個SyncRunner對象裏面有一個LinkedBlockingQueue(syncFutures,大小爲參數{hbase.regionserver.handler.count默認值200}*3 
另外這裏的SyncFuture是每一個rpcHandler線程擁有一個,由wal中的private final Mapide

class RingBufferEventHandler implements EventHandler<RingBufferTruck>, LifecycleAware { private final SyncRunner [] syncRunners; private final SyncFuture [] syncFutures; ... } private class SyncRunner extends HasThread { private volatile long sequence; // Keep around last exception thrown. Clear on successful sync. private final BlockingQueue<SyncFuture> syncFutures; ... }

這裏在處理ringBuffer中的syncFuture時,不是每有一個就提交到syncRunner處理,而是按批來處理的,這裏的批分2種狀況:性能

  1. 從ringBuffer中取到的一批數據(爲提升效率,在disruptor框架中是按批從ringBuffer中取數據的,具體的請看disruptor的相關文檔),若是這批數據中的syncFuture個數<{hbase.regionserver.handler.count默認值200},則按一批處理
  2. 若是這一批數據中的syncFuture個數>={hbase.regionserver.handler.count默認值200}個數,則按{hbase.regionserver.handler.count默認值200}分批處理。

若是達到了批大小,就從syncRunner數組中順序選擇下一個SyncRunner,將這批數據插入該SyncRunner的BlockingQueue中。最後由SyncRunner線程進行hdfs文件同步處理。爲保證數據的不丟失,rpc請求須要保證wal日誌寫入成功後才能返回,這裏HBase作了一系列的優化處理的操做。優化

wal滾動

經過wal日誌切換,這樣能夠避免產生單獨的過大的wal日誌文件,這樣能夠方便後續的日誌清理(能夠將過時日誌文件直接刪除)另外若是須要使用日誌進行恢復時,也能夠同時解析多個小的日誌文件,縮短恢復所需時間。 
wal觸發切換的場景有以下幾種:spa

  1. SyncRunner線程在處理日誌同步後,若是有異常發生,就會調用requestLogRoll發起日誌滾動請求
  2. SyncRunner線程在處理日誌同步後, 檢查當前在寫的wal的日誌大小是否超過配置{hbase.regionserver.hlog.blocksize默認爲hdfs目錄塊大小}*{hbase.regionserver.logroll.multiplier默認0.95},超事後一樣調用requestLogRoll發起日誌滾動請求
  3. 每一個RegionServer有一個LogRoller線程會按期滾動日誌,滾動週期由參數{hbase.regionserver.logroll.period默認值1個小時}控制

這裏前面2種場景調用requestLogRoll發起日誌滾動請求,最終也是經過LogRoller來執行日誌滾動的操做。

wal失效

當memstore中的數據刷新到hdfs後,那對應的wal日誌就不須要了,FSHLog中有記錄當前memstore中各region對應的最老的sequenceId,若是一個日誌中的各個region的操做的最新的sequenceId均小於wal中記錄的各個需刷新的region的最老sequenceId,說明該日誌文件就不須要了,因而就會將該日誌文件從./WALs目錄移動到./oldWALs目錄。這塊是在前面日誌滾動完成後調用cleanOldLogs來處理的。

wal刪除

因爲wal日誌還會用於跨集羣的同步處理,因此wal日誌失效後並不會當即刪除,而是移動到oldWALs目錄。由HMaster中的LogCleaner這個Chore線程來負責wal日誌的刪除,在LogCleaner內部經過參數{hbase.master.logcleaner.plugins}以插件的方式來篩選出能夠刪除的日誌文件。目前配置的插件有ReplicationLogCleaner、SnapshotLogCleaner和TimeToLiveLogCleaner

  1. TimeToLiveLogCleaner: 日誌文件最後修改時間在配置參數{hbase.master.logcleaner.ttl默認600秒}以前的能夠刪除
  2. ReplicationLogCleaner:若是有跨集羣數據同步的需求,經過該Cleaner來保證那些在同步中的日誌不被刪除
  3. SnapshotLogCleaner: 被表的snapshot使用到了的wal不被刪除

總結

在本篇中對HBase中wal日誌的整個週期進行了敘述,能對wal的處理過程有了總體的瞭解,後續在單獨說說WAL日誌的恢復的內容。

參考資料: 
1. http://hbasefly.com/2016/03/23/hbase_writer/ 
2. http://hbasefly.com/2016/10/29/hbase-regionserver-recovering/

轉:https://blog.csdn.net/xiangel/article/details/54424900

相關文章
相關標籤/搜索