天天看點

hbase源碼系列(七)Snapshot的過程

直接進入主題吧,上代碼。

從代碼上看得出來,啟用的表和被禁用的表走的是兩個不同的方法。

先看snapshotenabledtable方法吧,看看線上的表是怎麼備份的。

這裡就兩步,先去看看snapshot前的準備工作吧,f3進入preparetotakesnapshot方法。這個方法裡面也沒幹啥,就是檢查一下是否可以對這個表做備份或者恢複的操作,然後就會重建這個工作目錄,這個工作目錄在.hbase-snapshot/.tmps下面,每個snapshot都有自己的目錄。

在snapshottable裡面把就線程送出一下,讓handler來處理了。

這些都不是重點,咱到handler那邊去看看吧,enabledtablesnapshothandler是繼承takesnapshothandler的,prepare方法和process方法都一樣,差別在于snapshotregions方法被重寫了。

看prepare方法還是檢查表的定義檔案在不在,我們直接進入process方法吧。

1、寫一個.snapshotinfo檔案到工作目錄下

2、把表的定義資訊寫一份到工作目錄下,即.tabledesc檔案

3、查找和表相關的region server和機器

4、開始備份

5、檢驗snapshot的結果

6、确認沒問題了,就把臨時目錄rename到正式目錄

  

我們直接到備份這一步去看吧,方法在enabledtablesnapshothandler裡面,重寫了。

這裡用到一個分布式事務,這裡被我叫做分布式事務,我也不知道它是不是事務,但是procedure這個詞我真的不好翻譯,叫過程也不合适。

我們進入procedurecoordinator的startprocedure看看吧。

先建立procedure,然後送出它,這塊沒什麼特别的,繼續深入進去submitprocedure方法也找不到什麼有用的資訊,我們得回到procedure類裡面去,它是一個callable的類,奧秘就在call方法裡面。

從sendglobalbarrierstart開始看吧,裡面就一句話。

再追殺下去。

1、首先是檢查abortnode ,什麼是abortnode ?每個procname在zk下面都有一個對應的節點,比如snapshot,然後在procname下面又分了acquired、reached、abort三個節點。檢查abort節點下面有沒有目前的執行個體。

2、在acquired節點為該執行個體建立節點,建立執行個體節點的時候,把snapshotdescription的資訊(在enabledtablesnapshothandler類裡面通過this.snapshot.tobytearray()傳進去的)放了進去,建立完成之後,在該執行個體節點下面監控各個region server的節點。如果發現已經有了,就更新procedure中的acquiringmembers清單和inbarriermembers,把節點從

acquiringmembers中删除,然後添加到inbarriermembers清單當中。

3、到這一步服務端的工作就停下來了,等到所有rs接收到指令之後通過執行個體節點當中儲存的表資訊找到相應的region建立子過程,子過程在acquired節點下建立節點。

4、收到所有rs的回複之後,它才會開始在reached節點建立執行個體節點,然後繼續等待。

5、rs完成任務之後,在reached的執行個體節點下面建立相應的節點,然後回複。

6、在确定所有的rs都完成工作之後,清理zk當中的相應proname節點。

<b>注意:</b>在這個過程當中,有任務的錯誤,都會在abort節點下面建立該執行個體的節點,rs上面的子過程一旦發現abort存在該節點的執行個體,就會取消該過程。

 snapshot這塊在region server是由regionserversnapshotmanager類裡面的procedurememberrpcs負責監測snapshot下面的節點變化,當發現acquired下面有執行個體之後,啟動新任務。

這塊折疊起來,不是咱們的重點,讓大家看看而已。我們直接進入subprocedure這個類裡面看看吧。

insidebarrier的實作在flushsnapshotsubprocedure這個類裡面,調用了flushsnapshot(),這個方法給每個region都開一個線程去送出。

我們接下來看看regionsnapshottask的call方法。

在對region操作之前,先上鎖,不讓讀了。然後就flushcache,這個方法很大,也好難懂哦,不過我們還是要迎接困難上,我折疊起來吧,想看的就看,不想看的就看我下面的寫的步驟吧。

1、擷取wal日志的flushid(要寫入到hfile當中,以後恢複的時候,要拿日志的flushid和hfile的flushid對比,小于hfile的flushid的就不用恢複了)

2、給memstore的做snapshot,從kvset集合轉移到snapshot集合

3、同步日志,寫入到硬碟

5、上一步的生成的檔案是儲存在臨時目錄中的,轉移到正式的目錄當中

6、更新memstore當中的大小

好,我們繼續看addregiontosnapshot方法,好累啊,尼瑪,這麼多步驟。

在工作目錄在.hbase-snapshot/.tmps/snapshotname/region/familyname/下面給hfile建立引用檔案。在建立引用檔案的時候,還要先判斷一下這個所謂的hfile是不是真的hfile,還是它本身就是一個引用檔案了。

如果已經是引用檔案的話,把舊的引用檔案裡面的内容寫入到新的引用檔案當中。

如果是一個正常的hfile的話,就建立一個空的引用檔案即可,以後我們可以通過它的名字找到它在snapshot下面相應的檔案。

okay,到這裡,每個rs的工作都完成了。

完成執行分布式事務,就是備份split過的region了,把之前的代碼再貼一次吧,折疊起來,需要的自己看。

備份啟用的表,現在已經結束了,但是備份禁用的表吧,前面說了差別是snapshotregions方法,但是方法除了做一些準備工作之外,就是snapshotdisabledregion。。。。是以snapshot到這裡就完了,下面我們<b>再回顧一遍吧</b>。

1、進行snapshot之前的準備,建立目錄,複制一些必要的資訊檔案等。

2、對于啟用的表,啟動分布式事務,rs接到任務,flush掉wal日志和memstore的資料,寫入檔案。

3、為hfile建立引用檔案,這裡的引用檔案居然是空的檔案,而且名字一樣,它不是真的備份hfile,這是什麼回事呢?這個要到下一章,從snapshot中恢複,才能弄明白了,這個和hbase的歸檔檔案機制有關系,hbase删除檔案的時候,不是直接删除,而是把它先放入archive檔案夾内。

繼續閱讀