技術實踐-HBase增量數據遷移的方法
概覽

● 本文主要是想談一下如何給HBase做增量數據的遷移,也就是遷移實時數據。在之前的博文HBase實用技巧:一種全量+增量數據的遷移方法-云社區-華為云 (huaweicloud.com)中提到HBase增量數據遷移可以使用Replication的方式去做,但是在實際搬遷時,要給原集群設置Replication可能需要重啟,這樣會影響業務,我們需要做到不停機遷移才行。
WAL原理
正常情況下,HBase新增的數據都是有日志記錄的,數據在落盤成HFile之前,任何一個Put和Delete操作都是記錄日志并存放在WALs目錄中,日志中包含了所有已經寫入Memstore但還未Flush到HFile的更改(edits)。
默認情況下每個RegionServer只會寫一個日志文件,該RS管理的所有region都在向這一個日志文件寫入Put和Delete記錄,直到日志文件大小達到128MB(由hbase.regionserver.hlog.blocksize設置)后roll出一個新的日志文件,總共可以roll出32個日志文件(由hbase.regionserver.maxlogs設置)。
如果日志文件未寫滿128MB,RegionServer間隔1小時也會roll出新一個新日志文件(由hbase.regionserver.logroll.period設置)。
當日志文件中涉及的所有region的記錄都flush成HFile后,這個日志文件就會轉移至oldWals目錄下歸檔, Master沒間隔10分鐘(hbase.master.cleaner.interval)會檢查oldWALs目錄下的過期日志文件,當文件過期時會被Master清理掉,(日志過期時間由hbase.master.logcleaner.ttl控制)。
RegionServer默認間隔1小時(由hbase.regionserver.optionalcacheflushinterval設置)會對它管理的region做一次flush動作,所以WALs目錄中一直會有新的日志文件生成,并伴隨著老的日志文件移動到oldWALs目錄中。
遷移方式
一、遷移oldWALs目錄中的文件,使用WALPlayer回放
由于日志文件文件最終移動到oldWALs目錄下,只需要寫個腳本,定時檢查oldWALs目錄下是否有新文件生成,如果有文件,則move至其他目錄,并使用WALPlayer工具對這個目錄進行回放。
優點:無代碼開發量,僅需腳本實現
缺點:無法做到實時,因為從數據寫入到最后到達oldWAL目錄會間隔很長時間。
二、開發獨立工具,解析日志文件,寫入目的集群
在網上查找遷移方法的時候了解到了阿里開發了一個專門的HBase遷移工具,可以實現不停機。通過閱讀其設計BDS - HBase數據遷移同步方案的設計與實踐了解到阿里開發了應用去讀取HBase的WAL日志文件并回放數據至目的集群。
優點:可以做到實時;
缺點:需要一定的代碼開發量;
要做出這樣一個工具,需要了解上面說的WAL文件歸檔的原理以及日志回放工具WALPlayer,下面簡單說一下可以怎么去實現。
獨立工具實現
這里簡單說明下如何去做這樣一個工具,只介紹讀取WAL方面,任務編排就不描述了
定時掃描WALs目錄獲取所有的日志文件,這里按ServerName去分組獲取,每個分組內根據WAL文件上的時間戳排序;
● 獲取所有RS的ServerName
ClusterStatus clusterStatus = admin.getClusterStatus(); Collection
● 根據ServerName去組成Path獲取日志
Path rsWalPath = new Path(walPath, serverName.getServerName()); List
● getFiles()參考HBase源碼中WALInputFormat.java中的實現,可以指定時間范圍去取日志文件
private List
對于取到的每一個WAL文件,當做一個任務Task執行遷移,這個task主要有下面一些步驟
● 使用WALFactory為每個日志文件創建一個Reader
WAL.Reader walReader = WALFactory.createReader(fileSystem, curWalPath, conf);
● 通過Reader去讀取key和edit,并記錄下position,為了加快寫入速度,這里可以優化為讀取多個entry
WAL.Entry entry = walReader.next(); WALKey walKey = entry.getKey(); WALEdit walEdit = entry.getEdit(); long curPos = reader.getPosition();
● 記錄position的目的是為了Reader的reset以及seek,因為這個原始WAL文件還正在寫入的時候,我們的Reader速度很可能大于原WAL的寫入速度,當Reader讀到底的時候,需要等待一段時間reset然后再重新讀取entry
WAL.Entry nextEntry = reader.next(); if (nextEntry == null) { LOG.info("Next entry is null, sleep 10000ms."); Thread.sleep(5000); curPos = reader.getPosition(); reader.reset(); reader.seek(curPos); continue; }
● 在讀取WAL的過程中很可能會遇到日志轉移到oldWALs目錄下,這個時候捕獲到FileNotFoundException時,需要重新生成一個oldWALs目錄下Reader,然后設置curPos繼續讀取文件,這個時候如果再次讀取到文件最后的時候,就可以關閉Reader了,因為oldWALs中的日志文件是固定大小的,不會再有追加數據。
這里需要注意的是這個參數hbase.master.logcleaner.ttl不能設置過小,否則會出現這個在oldWALs目錄下的日志文件還沒讀取完被清理掉了。
Path oldWALPath = new Path(oldWalPath, walFileName); WAL.Reader reader = WALFactory.createReader(fileSystem, oldWALPath, conf); reader.seek(curPos)
● 根據通過WAL.Reader可以讀取到walKey,walEdit進而解析出Cell并寫入目的集群,這個可以參考WALPlay的map()方法
EI企業智能 HBase 數據遷移 智能數據 表格存儲服務 CloudTable
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。