天天看點

hbase源碼系列(十)HLog與日志恢複

hbase在寫入資料之前會先寫入memstore,成功了再寫入hlog,當memstore的資料丢失的時候,還可以用hlog的資料來進行恢複,下面先看看hlog的圖。

hbase源碼系列(十)HLog與日志恢複

舊版的hlog是實際上是一個sequcenefile,0.96的已經使用protobuf來進行序列化了。從writer和reader上來看hlog的都是entry的,換句話說就是,它的每一條記錄就是一個entry。

是以上面那個圖已經不準确了,hlogkey沒變,但是value缺不是keyvalue,而是waledit。

下面我們看看hlogkey的五要素,region、tablename、log的順序、寫入時間戳、叢集id。

下面看看waledit的屬性, 這裡隻列出來一個重要的,它是内部持有的一群keyvalue。。

hlog的具體實作類是fshlog,一個region server有兩個fshlog,一個負責rs上面所有的使用者region的日志,一個負責rs上面的meta表的region的日志。

對于日志來說,我們關心的是它如何保證一緻性和準确性,在需要它的時候可以發揮救命作用。

對于meta region的hlog寫入之後,它會立即同步到硬碟,非meta表的region,它會先把entry添加到一個隊列裡面等待同步。

它這裡是有一個判斷條件的,如果判斷條件不成立就立即同步,等待this.optionalflushinterval時間,預設的同步間隔是1000,它是通過參數hbase.regionserver.optionallogflushinterval設定。unflushedentries是一個atomiclong在寫入entry的時候遞增,syncedtillhere是一個volatile long,同步完成之後也是變大,因為可能被多個線程調用同步操作,是以它是volatile的,從條件上來看,如果沒有日志需要同步就等待一秒再進行判斷,如果有日志需要同步,也是立馬就寫入硬碟的,如果發生錯誤,就是調用requestlogroll方法,進行復原,這個復原比較有意思,它是跑過去flush掉memstore中的資料,把他們寫入硬碟。

下面是復原的方法。中間我忽略了幾步,然後找到logroller中的這段代碼。

找出來需要flush的region,然後計劃flush。

逐個對比,找出來未flush memstore的比輸出的檔案的hlog流水号還小的region,當它準備flush memstore之前會調用startcacheflush方法來把region從oldestunflushedseqnums這個map當中去除,添加到已經flush的map當中。

那啥時候會用到這個呢,在region打開的時候,我們從hregionserver的openregion方法一路跟蹤,中間曆經openmetahandler,再到hregion.openhregion方法,終于在initializeregionstores方法裡面找到了那麼一句話。

高潮來了!!!

呵呵,讀取recovered.edits下面的日志,符合條件的就加到memstore裡面去,完成之後,就把這些檔案删掉。大家也看到了,這裡通篇講到一個logseqnum,哪裡都有它的身影,它實際上是fshlog當中的一個遞增的atomiclong,每當往fslog裡面寫入一條日志的時候,它都會加一,然後memstore請求flush的時候,會調用fslog的startcacheflush方法,擷取(logseqnum+1)回來,然後寫入到storefile的sequenceid字段,再次拿出來的時候,就周遊這個hstore下面的storefile的logseqnum,取出來最大的跟它比較,小于它的都已經寫過了,沒必要再寫了。

好了,hlog結束了,累死我了,要睡了。<b></b>

繼續閱讀