IT技(ji)術(shu)互動交流平(ping)台

贵州快3官网

作(zuo)者︰Yijian  來源︰IT165收集  發(fa)布日期︰2020-02-20 15:22:17

解決的(de)問(wen)題

HBase的(de)Write Ahead Log (WAL)提供了一種高(gao)並發(fa)、持久化的(de)日志保(bao)存(cun)與回放機制。每一個(ge)業務數據的(de)寫入操作(zuo)(PUT / DELETE)執(zhi)行前(qian),都會記賬在(zai)WAL中。

如果出(chu)現HBase服(fu)務器宕機,則可(ke)以從WAL中回放執(zhi)行之前(qian)沒有完成的(de)操作(zuo)。

本(ben)文主要探(tan)討(tao)HBase的(de)WAL機制,如何從線程模型、消(xiao)息機制pin)de)層面上,解決這(zhe)些問(wen)題︰

1. 由于多個(ge)HBase客(ke)戶端可(ke)以對(dui)某一台HBase Region Server發(fa)起並發(fa)的(de)業務數據寫入請求,因(yin)此WAL也要支持並發(fa)的(de)多線程日志寫入。——確保(bao)日志寫入的(de)線程安全、高(gao)並發(fa)。

2. 對(dui)于單個(ge)HBase客(ke)戶端,它(ta)在(zai)WAL中的(de)日志順序,應該與這(zhe)個(ge)客(ke)戶端發(fa)起的(de)業務數據寫入請求的(de)順序一致。

(對(dui)于以上兩點(dian)要求,大(da)家很容(rong)易(yi)想到,用一個(ge)隊(dui)列就搞定了。見下文的(de)架構圖(tu)。)

3. 為了保(bao)證高(gao)可(ke)靠(kao),日志不僅要寫入文件系統的(de)內(na)存(cun)緩存(cun),而且應該盡快、強(qiang)制刷(shua)到磁盤(pan)上(即WAL的(de)Sync操作(zuo))。但是Sync太頻(pin)繁bao) 閱(yue)芑岊洳睢K裕/p>

 (1) Sync應當在(zai)多個(ge)後台線程tao)幸觳街zhi)行

 (2) 頻(pin)繁的(de)多個(ge)Sync,可(ke)以合(he)並為一次Sync——適當放松(song)對(dui)可(ke)靠(kao)性的(de)要求,提高(gao)性yue)塴/p>

架構圖(tu)——線程模型、消(xiao)息機制

下面是我畫的(de)HBase WAL架構圖(tu)。我在(zai)圖(tu)上加了不少注(zhu)解,所以這(zhe)張圖(tu)應該是自(zi)解釋的(de)︰

 Region Server RPC服(fu)務線程

這(zhe)些線程處理HBase客(ke)戶端通過(guo)RPC服(fu)務調用(實際上是Google Protobuf服(fu)務調用)發(fa)出(chu)的(de)業務數據寫入請求。在(zai)上圖(tu)的(de)例(li)子(zi)中,“Region Server RPC服(fu)務線程1” 做了3個(ge)Row的(de)Append操作(zuo),和一個(ge)強(qiang)制刷(shua)磁盤(pan)的(de)Sync操作(zuo)。

Sync操作(zuo)是為了確保(bao)之前(qian)的(de)Append操作(zuo)(包括涉及的(de)業務數據)一定可(ke)靠(kao)地記錄(lu)到了磁盤(pan)上的(de)日志ju)校 緩Base才能做後續相(xiang)對(dui)不可(ke)靠(kao)的(de)復(fu)雜操作(zuo),比如寫入MemStore。——這(zhe)就是Write Ahead的(de)語(yu)義。

從架構圖(tu)中可(ke)見,並發(fa)的(de)Append操作(zuo)只是往隊(dui)列中增加了Append請求對(dui)象。

這(zhe)里的(de)隊(dui)列是一個(ge)LMAX Disrutpor RingBuffer(我的(de)這(zhe)篇文章作(zuo)了介紹(shao)),你可(ke)以簡單理解為是一個(ge)無鎖高(gao)並發(fa)隊(dui)列。

Append的(de)具體代碼如下︰

對(dui)于Sync操作(zuo)︰

(1)往隊(dui)列里放一個(ge)SyncFuture對(dui)象,代表一次Sync操作(zuo)請求。

每一個(ge)SyncFuture都有一個(ge)自(zi)增的(de)Sequence ID——這(zhe)是全局(ju)唯一的(de),由LMAX Disrutpor隊(dui)列創(chuang)建。後來的(de)SyncFuture的(de)Sequence ID更高(gao)。

(2)調用SyncFuture.get()阻塞等待,直(zhi)到後台線程(架構圖(tu)中的(de)SyncRunner)通知SyncFuture退(tui)出(chu)阻塞,表明WAL日志已經保(bao)存(cun)在(zai)了磁盤(pan)上。

WAL日志消(xiao)費線程

WAL機制中,只有一個(ge)WAL日志消(xiao)費線程,從隊(dui)列中獲取Append和Sync操作(zuo)。這(zhe)樣一個(ge)多生產者,單消(xiao)費者的(de)模式,決定了WAL日志並發(fa)寫入時(shi)日志的(de)全局(ju)唯一順序。

1. 對(dui)于獲取到的(de)Append操作(zuo),直(zhi)接調用Hadoop Sequence File Writer將這(zhe)個(ge)Append操作(zuo)(包括元數據和row key, family, qualifier, timestamp, value等業務數據)寫入文件。

    因(yin)此WAL日志文件使(shi)用的(de)是Hadoop Sequence文件格(ge)式。當然,它(ta)也可(ke)以替換成其他存(cun)儲格(ge)式,如Avro。

    Hadoop Sequence文件格(ge)式不再這(zhe)里累述,其主要特點(dian)是︰

   (1) 二進制格(ge)式。row key, family, qualifier, timestamp, value等HBase byte[]數據,都原封(feng)不動地順序寫入文件。

   (2) Sequence文件中,每隔若干行,會插入一個(ge)16字(zi)節的(de)魔數作(zuo)為分隔符。這(zhe)樣如果文件損壞,導致某一行殘缺不全,可(ke)以通過(guo)這(zhe)個(ge)魔數分隔符跳過(guo)這(zhe)一行,繼(ji)續讀取下一個(ge)完整的(de)行。

   (3) 支持壓縮。可(ke)以按行壓縮。也可(ke)以按塊壓縮(將多行打成一個(ge)塊)

2. 對(dui)于獲取到的(de)Sync操作(zuo),會提交給後台SyncRunner的(de)線程池(見上文架構圖(tu))異步執(zhi)行。

以上的(de)this.syncRunners就是SyncRunner線程池。可(ke)以看到,通過(guo)計算syncRunnerIndex,采用了簡單的(de)輪循(xun)提交算法(fa)。

另外,WAL日志消(xiao)費線程,會嘗試收集一批SyncFuture對(dui)象(即sync操作(zuo)),一次提交給SyncRunner。

        所以,在(zai)以上代碼中,可(ke)以看到傳入offer()方法(fa)的(de),是this.syncFutures這(zhe)一SyncFutures[]數組,而不是單個(ge)SyncFuture對(dui)象。

        收集一批次再提交,性yue)鼙冉蝦謾5 塹?ge)批次需(xu)要積攢的(de)SyncFuture對(dui)象越多,則Sync的(de)及時(shi)性越差,會導致前(qian)台Region Server RPC服(fu)務線程阻塞在(zai)SyncFuture.get()上的(de)時(shi)間(jian)就越長。

        因(yin)此,這(zhe)里存(cun)在(zai)吞吐量和tu)笆shi)性之間(jian)的(de)平(ping)衡(heng)。HBase為了支持海(hai)量數據的(de)寫入,在(zai)這(zhe)里更傾向于高(gao)吞吐量,體現在(zai)了以下注(zhu)釋中。具體多少個(ge)SyncFuture構成一個(ge)批次,有一定的(de)策(ce)略(lue),在(zai)此不再累述。

SyncRunner線程

1. 從隊(dui)列中獲取一個(ge)由WAL日志消(xiao)費線程提交的(de)SyncFuture(下圖(tu)紅框中的(de)代碼)。

2. 調用文件系統API,執(zhi)行sync()操作(zuo)(下圖(tu)藍(lan)框中的(de)代碼)

合(he)並多次頻(pin)繁的(de)sync()操作(zuo),提高(gao)性yue)塴p>        上文提到,WAL日志消(xiao)費線程一次會提交多個(ge)SyncFuture。對(dui)此,SyncRunner線程tao)換崧涫抵zhi)行其中最(zui)新的(de)SyncFuture(也就是Sequence ID最(zui)大(da)的(de)那個(ge))所代表的(de)Sync操作(zuo)。而忽略(lue)之前(qian)的(de)SyncFuture。

        這(zhe)就是下圖(tu)綠框中的(de)代碼。

3. 如果sync()完成,或者因(yin)為上面提到的(de)合(he)並忽略(lue)了某一個(ge)SyncFuture,那麼會調用releaseSyncFuture() ==> Object.notify()來通知SyncFuture阻塞退(tui)出(chu)。

   之前(qian)阻塞在(zai)SyncFuture.get()上的(de)Region Server RPC服(fu)務線程就可(ke)以繼(ji)續往下執(zhi)行了。

至此,整個(ge)WAL寫入流程完成。

總(zong)結

我覺得(de)對(dui)線程並發(fa)寫入文件時(shi),用隊(dui)列來協調,保(bao)證日志寫入的(de)順序,這(zhe)還是比較容(rong)易(yi)想到的(de)。

但是,提供Sync() API確保(bao)日志寫入的(de)可(ke)靠(kao)性,同時(shi)避免頻(pin)繁的(de)Sync()操作(zuo)影響性yue)塴mdash;—這(zhe)是HBase WAL實現的(de)一大(da)亮(liang)點(dian)。

後續我再研(yan)究研(yan)究WAL的(de)checkpoint和讀取WAL回放機制,再和大(da)家分享。

Tag標簽︰線程  架構  模型  
  • 贵州快3官网

About IT165 - 廣告(gao)服(fu)務 - 隱私聲(sheng)明 - 版(ban)權申明 - 免責(ze)條款 - 網(wang)站地圖(tu) - 網(wang)友投稿 - 聯系方式
本(ben)站內(na)容(rong)來自(zi)于互聯網(wang),僅供用于網(wang)絡技(ji)術(shu)學習,學習中請遵循(xun)相(xiang)關法(fa)律法(fa)規
贵州快3官网 | 下一页