Hbase的WAL在RegionServer基本調用過程


版權聲明:本文由熊訓德原創文章,轉載請注明出處: 
文章原文鏈接:https://www.qcloud.com/community/article/221

來源:騰雲閣 https://www.qcloud.com/community

 

Hbase是一個高可靠性、高性能、面向列、可伸縮的分布式存儲系統,利用HBase技術可在廉價PC Server上搭建起大規模結構化存儲集群。本文檔用於說明hbase的wal簡單原理以及從源碼的角度分析一個“寫”請求是如何到達wal,wal又會做哪些請求。

本文檔用於說明hbase的wal簡單原理以及從源碼的角度分析一個“寫”請求是如何到達wal,wal又會做哪些請求。特別說明Hbase不同版本的wal的源碼差異比較大,但是原理幾乎類似,本文檔是采用當前線上使用版本(Hbase1.1.3)來分析的。

簡單原理

有關hbase的wal基本原理在《Hbase權威指南》以及網絡教程中敘述的算比較清晰詳盡,在此只做簡單的敘述。

hbase是基於LSM樹的存儲系統,它使用日志文件和內存存儲來的存儲架構將隨機寫轉換成順序寫,以此保證穩定的數據插入速率。而這里說的日志文件即是wal文件,用於在服務器崩潰后回滾還沒持久化的數據。

WAL(Write-Ahead-Log)是HBase的RegionServer在處理數據插入和刪除的過程中用來記錄操作內容的一種日志。大致過程如下圖所示,首先客戶端啟動一個操作來修改數據,每一個修改都封裝到KeyValue對象實例中,並通過RPC調用發送到含有匹配Region的HRegionServer。一旦KeyValue到達,它們就會被發送管理相應行的HRegion實例。數據被寫到WAL,然后被放入到實際擁有記錄的存儲文件的MemStore中。同時還會檢查MemStore是否滿了,如果滿了就會被刷寫到磁盤中去。

wal調用鏈源碼分析

本節將從源碼角度如上所簡述分析hbase的一個“寫”過程。

其中基本調用過程如下:

從時序圖中可以大體看到

  1. 首先client端先把put/delete等api操作封裝成List,然后使用protobuf協議使用rpc服務發送到對應的HRegionServer,HRegionServer調用execRegionServerService()方法解析發送過來的protobuf協議二進制包,通過serviceName找到相應的service並調用callMethod方法執行:

  2. put/delet等“寫”操作會使用MultiRowMutationService這個service來作用,在service中將會調用mutateRows()方法去處理List,真正調用mutateRows()的是MultiRowMutationService的一個實現類MultiRowMutationEndpoint,MultiRowMutationEndpoint類實現了hbase的行事務。從MultiRowMutationEndpoint類文檔可以看出其主要作用:

    mutateRows()方法會row所找到對應的Region,並調用其對應實例HRegion的mutateRowsWithLocks方法具體實現寫入過程。

  3. 在HRegion類中mutateRowsWithLocks方法查看有沒執行器(RowProcessor),如果沒有則創建一個再調用processRowsWithLocks()方法。processRowsWithLocks方法是整個“寫”操作最核心的方法:把寫wal,刷wal以及寫memstore流程都在這里流轉。在這里包括異常處理一共有14步之多。

    它的原型如下:

    其中processor的實現類是MultiRowMutationProcessor。

    雖然processRowsWithLocks方法步驟很多,但是最關鍵的是如下幾步:

    在這里,HRegion將會對Region加鎖,加鎖的方式是把所有寫row相關的行鎖都拿到的二階段鎖方式。

    在這里將會把List放入,但是這里並不是真正的放到了memstore,真正的執行會等sync()方法把日志或者說WALEdite真正刷入磁盤后,通過mvcc版本號異步通知再把數據寫到memstore。

    在這里HRegion會把封裝好的WALEdit使用FSHLog的append方法追加到日志文件,但是由於文件本身在內存中有緩存的原因,還需要調用sync刷入磁盤。這里只是把WALEdit數據放到一個LMAX Disrutpor RingBuffer中。這個RingBuffer是一個線程安全的消息隊列,在wal中主要用於有效且安全的協調多個生產者一個消費者模型。其中多個生產者就是這個append方法,將會有很多client產生數據都放到這個消息隊列中,但是只有一個消費者從這個隊列中取數據並調用sync方法把數據從緩存刷到磁盤,這樣能保證WAL日志並發寫入時日志的全局唯一順序。

    (其中有關LMAX Disrutpor RingBuffer可以參看文章,介紹的非常詳盡:https://github.com/LMAX-Exchange/disruptor/wiki/Introduction)

    在這步中會會調用syncOrDefer方法,除了metaRegion,syncOrDefer將根據client設置的持久化等級選擇是否調用wal(FSHLog)的sync方法

HBase中可以通過設置WAL的持久化等級決定是否開啟WAL機制、以及HLog的落盤方式。

client可以通過設置WAL持久化等級,如代碼:put.setDurability(Durability. SYNC_WAL );

1.1.3版本的WAL的持久化等級分為如下四個等級:

USER_DEFAULT:默認如果用戶沒有指定持久化等級,HBase使用SYNC_WAL等級持久化數據。

SKIP_WAL:只寫緩存,不寫HLog日志。這種方式因為只寫內存(memstore),因此可以提升寫入性能,但是數據有丟失的風險。

ASYNC_WAL:異步將數據寫入HLog日志中。

SYNC_WAL:同步將數據寫入日志文件中,有可能只是被寫入文件系統中,並沒有真正落盤。

FSYNC_WAL:同步將數據寫入日志文件並強制落盤。最嚴格的日志寫入等級,可以保證數據不會丟失,但是性能相對比較差。

如代碼中所示當前sync_wal和fsync_wal采用的是同一策略都是:調用HFLog的sync()方法。sync()是一個阻塞方法,需要等到數據真正的刷到磁盤后,便會喚醒它,然后工作線程返回寫入memstore,完成一次“寫”操作。

小結

Hbase是一個高可靠性、高性能、面向列、可伸縮的分布式存儲系統,利用HBase技術可在廉價PC Server上搭建起大規模結構化存儲集群。本文檔在介紹hbase基本“寫”原理后着重從源碼角度,比較淺顯地分析了一個“寫”操作后在RegionServer的調用過程,為以后繼續更深入學習研究hbase“寫”過程梳理了脈絡。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM