HBase數(shù)據(jù)遷移方案介紹
一、前言
HBase數(shù)據(jù)遷移是很常見的操作,目前業(yè)界主要的遷移方式主要分為以下幾類:
圖1.HBase數(shù)據(jù)遷移方案
從上面圖中可看出,目前的方案主要有四類,Hadoop層有一類,HBase層有三類。下面分別介紹一下。
二、Hadoop層數(shù)據(jù)遷移
2.1 方案介紹
Hadoop層的數(shù)據(jù)遷移主要用到DistCp(Distributed Copy), 官方描述是:DistCp(分布式拷貝)是用于大規(guī)模集群內(nèi)部和集群之間拷貝的工具。它使用Map/Reduce實(shí)現(xiàn)文件分發(fā),錯誤處理和恢復(fù),以及報告生成。它把文件和目錄的列表作為map任務(wù)的輸入,每個任務(wù)會完成源列表中部分文件的拷貝。
我們知道MR程序適合用來處理大批量數(shù)據(jù), 其拷貝本質(zhì)過程是啟動一個MR作業(yè),不過DisctCp只有map,沒有reducer。在拷貝時,由于要保證文件塊的有序性,轉(zhuǎn)換的最小粒度是一個文件,而不像其它MR作業(yè)一樣可以把文件拆分成多個塊啟動多個map并行處理。如果同時要拷貝多個文件,DisctCp會將文件分配給多個map,每個文件單獨(dú)一個map任務(wù)。我們可以在執(zhí)行同步時指定-m參數(shù)來設(shè)定要跑的map數(shù)量,默認(rèn)設(shè)置是20。如果是集群間的數(shù)據(jù)同步,還需要考慮帶寬問題,所以在跑任務(wù)時還需要設(shè)定 bandwitdh 參數(shù),以防止一次同步過多的文件造成帶寬過高影響其它業(yè)務(wù)。同時,由于我們HBase集群一般是不會開MR調(diào)度的,所以這里還需要用到單獨(dú)的MR集群來作主備數(shù)據(jù)同步,即在跑任務(wù)時還需要指定mapreduce相關(guān)參數(shù)。
簡單的distcp參數(shù)形式如下:
- hadoop distcp hdfs://src-hadoop-address:9000/table_name hdfs://dst-hadoop-address:9000/table_name
如果是獨(dú)立的MR集群來執(zhí)行distcp,因為數(shù)據(jù)量很大,一般是按region目錄粒度來傳輸,同時傳輸?shù)侥繕?biāo)集群時,我們先把文件傳到臨時目錄,最后再目的集群上load表,我們用到的形式如下:
- hadoop distcp \
- -Dmapreduce.job.name=distcphbase \
- -Dyarn.resourcemanager.webapp.address=mr-master-ip:8088 \
- -Dyarn.resourcemanager.resource-tracker.address=mr-master-dns:8093 \
- -Dyarn.resourcemanager.scheduler.address=mr-master-dns:8091 \
- -Dyarn.resourcemanager.address=mr-master-dns:8090 \
- -Dmapreduce.jobhistory.done-dir=/history/done/ \
- -Dmapreduce.jobhistory.intermediate-done-dir=/history/log/ \
- -Dfs.defaultFS=hdfs://hbase-fs/ \
- -Dfs.default.name=hdfs://hbase-fs/ \
- -bandwidth 20 \
- -m 20 \
- hdfs://src-hadoop-address:9000/region-hdfs-path \
- hdfs://dst-hadoop-address:9000/tmp/region-hdfs-path
在這個過程中,需要注意源端集群到目的端集群策略是通的,同時hadoop/hbase版本也要注意是否一致,如果版本不一致,最終load表時會報錯。
2.2 方案實(shí)施
遷移方法如下:
第一步,如果是遷移實(shí)時寫的表,最好是停止集群對表的寫入,遷移歷史表的話就不用了,此處舉例表名為test;
第二步, flush表, 打開HBase Shell客戶端,執(zhí)行如下命令:
- hbase> flush 'test'
第三步,拷貝表文件到目的路徑,檢查源集群到目標(biāo)集群策略、版本等,確認(rèn)沒問題后,執(zhí)行如上帶MR參數(shù)的命令
第四步, 檢查目標(biāo)集群表是否存在,如果不存在需要創(chuàng)建與原集群相同的表結(jié)構(gòu)
第五步,在目標(biāo)集群上,Load表到線上,在官方Load是執(zhí)行如下命令:
- hbase org.jruby.Main add_table.rb /hbase/data/default/test
對于我們來說,因我們先把文件同步到了臨時目錄,并不在原表目錄,所以我們采用的另一種形式的load,即以region的維度來Load數(shù)據(jù)到線上表,怎么做呢,這里用到的是org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles這個類,即以bulkload的形式來load數(shù)據(jù)。上面同步時我們將文件同步到了目的集群的/tmp/region-hdfs-path目錄,那么我們在Load時,可以用如下命令來Load region文件:
- hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles -Dhbase.mapreduce.bulkload.max.hfiles.perRegion.perFamily=1024 hdfs://dst-hadoop-address:9000/tmp/region-hdfs-path/region-name table_name
這里還用到一個參數(shù)hbase.mapreduce.bulkload.max.hfiles.perRegion.perFamily, 這個表示在bulkload過程中,每個region列族的HFile數(shù)的上限,這里我們是限定了1024,也可以指定更少,根據(jù)實(shí)際需求來定。
第六步,檢查表數(shù)據(jù)是否OK,看bulkload過程是否有報錯
在同步過程中,我們?yōu)榧訅K同步速度,還會開個多線程來并發(fā)同步文件,這個可根據(jù)實(shí)際數(shù)據(jù)量和文件數(shù)來決定是否需要使用并發(fā)同步。
三、HBase層數(shù)據(jù)遷移
3.1 copyTable方式
copyTable也是屬于HBase數(shù)據(jù)遷移的工具之一,以表級別進(jìn)行數(shù)據(jù)遷移。copyTable的本質(zhì)也是利用MapReduce進(jìn)行同步的,與DistCp不同的時,它是利用MR去scan 原表的數(shù)據(jù),然后把scan出來的數(shù)據(jù)寫入到目標(biāo)集群的表。這種方式也有很多局限,如一個表數(shù)據(jù)量達(dá)到T級,同時又在讀寫的情況下,全量scan表無疑會對集群性能造成影響。
來看下copyTable的一些使用參數(shù):
- Usage: CopyTable [general options] [--starttime=X] [--endtime=Y] [--new.name=NEW] [--peer.adr=ADR] <tablename>
- Options:
- rs.class hbase.regionserver.class of the peer cluster
- specify if different from current cluster
- rs.impl hbase.regionserver.impl of the peer cluster
- startrow the start row
- stoprow the stop row
- starttime beginning of the time range (unixtime in millis)
- without endtime means from starttime to forever
- endtime end of the time range. Ignored if no starttime specified.
- versions number of cell versions to copy
- new.name new table's name
- peer.adr Address of the peer cluster given in the format
- hbase.zookeeer.quorum:hbase.zookeeper.client.port:zookeeper.znode.parent
- families comma-separated list of families to copy
- To copy from cf1 to cf2, give sourceCfName:destCfName.
- To keep the same name, just give "cfName"
- all.cells also copy delete markers and deleted cells
- Args:
- tablename Name of the table to copy
- Examples:
- To copy 'TestTable' to a cluster that uses replication for a 1 hour window:
- $ bin/hbase org.apache.hadoop.hbase.mapreduce.CopyTable --starttime=1265875194289 --endtime=1265878794289 --peer.adr=server1,server2,server3:2181:/hbase --families=myOldCf:myNewCf,cf2,cf3 TestTable
- For performance consider the following general options:
- -Dhbase.client.scanner.caching=100
- -Dmapred.map.tasks.speculative.execution=false
從上面參數(shù),可以看出,copyTable支持設(shè)定需要復(fù)制的表的時間范圍,cell的版本,也可以指定列簇,設(shè)定從集群的地址,起始/結(jié)束行鍵等。參數(shù)還是很靈活的。
copyTable支持如下幾個場景:
1、表深度拷貝:相當(dāng)于一個快照,不過這個快照是包含原表實(shí)際數(shù)據(jù)的,0.94.x版本之前是不支持snapshot快照命令的,所以用copyTable相當(dāng)于可以實(shí)現(xiàn)對原表的拷貝, 使用方式如下:
- create 'table_snapshot',{NAME=>"i"}
- hbase org.apache.hadoop.hbase.mapreduce.CopyTable --new.name=tableCopy table_snapshot
2、集群間拷貝:在集群之間以表維度同步一個表數(shù)據(jù),使用方式如下:
- create 'table_test',{NAME=>"i"} #目的集群上先創(chuàng)建一個與原表結(jié)構(gòu)相同的表
- hbase org.apache.hadoop.hbase.mapreduce.CopyTable --peer.adr=zk-addr1,zk-addr2,zk-addr3:2181:/hbase table_test
3、增量備份:增量備份表數(shù)據(jù),參數(shù)中支持timeRange,指定要備份的時間范圍,使用方式如下:
- hbase org.apache.hadoop.hbase.mapreduce.CopyTable ... --starttime=start_timestamp --endtime=end_timestamp
4、部分表備份:只備份其中某幾個列族數(shù)據(jù),比如一個表有很多列族,但我只想備份其中幾個列族數(shù)據(jù),CopyTable提供了families參數(shù),同時還提供了copy列族到新列族形式,使用方式如下:
- hbase org.apache.hadoop.hbase.mapreduce.CopyTable ... --families=srcCf1,srcCf2 #copy cf1,cf2兩個列族,不改變列族名字
- hbase org.apache.hadoop.hbase.mapreduce.CopyTable ... --families=srcCf1:dstCf1, srcCf2:dstCf2 #copy srcCf1到目標(biāo)dstCf1新列族
總的來說,CopyTable支持的范圍還是很多的,但因其涉及的是直接HBase層數(shù)據(jù)的拷貝,所以效率上會很低,同樣需要在使用過程中限定掃描原表的速度和傳輸?shù)膸挘@個工具實(shí)際上使用比較少,因為很難控制。
3.2 Export/Import方式
此方式與CopyTable類似,主要是將HBase表數(shù)據(jù)轉(zhuǎn)換成Sequence File并dump到HDFS,也涉及Scan表數(shù)據(jù),與CopyTable相比,還多支持不同版本數(shù)據(jù)的拷貝,同時它拷貝時不是將HBase數(shù)據(jù)直接Put到目標(biāo)集群表,而是先轉(zhuǎn)換成文件,把文件同步到目標(biāo)集群后再通過Import到線上表。主要有兩個階段:
Export階段: 將原集群表數(shù)據(jù)Scan并轉(zhuǎn)換成Sequence File到Hdfs上,因Export也是依賴于MR的,如果用到獨(dú)立的MR集群的話,只要保證在MR集群上關(guān)于HBase的配置和原集群一樣且能和原集群策略打通(master®ionserver策略),就可直接用Export命令,如果沒有獨(dú)立MR集群,則只能在HBase集群上開MR,若需要同步多個版本數(shù)據(jù),可以指定versions參數(shù),否則默認(rèn)同步最新版本的數(shù)據(jù),還可以指定數(shù)據(jù)起始結(jié)束時間,使用如下:
- # output_hdfs_path可以直接是目標(biāo)集群的hdfs路徑,也可以是原集群的HDFS路徑,如果需要指定版本號,起始結(jié)束時間
- hbase org.apache.hadoop.hbase.mapreduce.Export <tableName> <ouput_hdfs_path> <versions> <starttime> <endtime>
Import階段: 將原集群Export出的SequenceFile導(dǎo)到目標(biāo)集群對應(yīng)表,使用如下:
- #如果原數(shù)據(jù)是存在原集群HDFS,此處input_hdfs_path可以是原集群的HDFS路徑,如果原數(shù)據(jù)存在目標(biāo)集群HDFS,則為目標(biāo)集群的HDFS路徑
- hbase org.apache.hadoop.hbase.mapreduce.Import <tableName> <input_hdfs_path>
3.3 Snapshot方式
3.3.1 snapshot介紹
此方式與上面幾中方式有所區(qū)別,也是目前用得比較多的方案,snapshot字面意思即快照, 傳統(tǒng)關(guān)系型數(shù)據(jù)庫也有快照的概念,HBase中關(guān)于快照的概念定義如下:
快照就是一份元信息的合集,允許管理員恢復(fù)到表的先前狀態(tài),快照不是表的復(fù)制而是一個文件名稱列表,因而不會復(fù)制數(shù)據(jù)
因不拷貝實(shí)際的數(shù)據(jù),所以整個過程是比較快的,相當(dāng)于對表當(dāng)前元數(shù)據(jù)狀態(tài)作一個克隆,snapshot的流程主要有三個步驟:
圖2.數(shù)據(jù)遷移圖
加鎖: 加鎖對象是regionserver的memstore,目的是禁止在創(chuàng)建snapshot過程中對數(shù)據(jù)進(jìn)行insert,update,delete操作
刷盤:刷盤是針對當(dāng)前還在memstore中的數(shù)據(jù)刷到HDFS上,保證快照數(shù)據(jù)相對完整,此步也不是強(qiáng)制的,如果不刷會,快照中數(shù)據(jù)有不一致風(fēng)險
創(chuàng)建指針: snapshot過程不拷貝數(shù)據(jù),但會創(chuàng)建對HDFS文件的指針,snapshot中存儲的就是這些指標(biāo)元數(shù)據(jù)
3.3.2 snapshot內(nèi)部原理
snapshot實(shí)際內(nèi)部是怎么做的呢,上面說到,snapshot只是對元數(shù)據(jù)信息克隆,不拷貝實(shí)際數(shù)據(jù)文件,我們以表test為例,這個表有三個region, 每個region分別有兩個HFile,創(chuàng)建snapshot過程如下:
圖3.snapshot創(chuàng)建內(nèi)部原理
創(chuàng)建的snapshot放在目錄/hbase/.hbase-snapshot/下, 元數(shù)據(jù)信息放在/hbase/.hbase-snapshot/data.manifest中, 如上圖所示,snapshot中也分別包含對原表region HFile的引用,元數(shù)據(jù)信息具體包括哪哪些呢:
- 1. snapshot元數(shù)據(jù)信息
- 2. 表的元數(shù)據(jù)信息&schema,即原表的.tableinfo文件
- 3. 對原表Hfile的引用信息
由于我們表的數(shù)據(jù)在實(shí)時變化,涉及region的Hfile合并刪除等操作,對于snapshot而言,這部分?jǐn)?shù)據(jù)HBase會怎么處理呢,實(shí)際上,當(dāng)發(fā)現(xiàn)spit/compact等操作時,HBase會將原表發(fā)生變化的HFile拷貝到/hbase/.archive目錄,如上圖中如果Region3的F31&F32發(fā)生變化,則F31和F32會被同步到.archive目錄,這樣發(fā)生修改的文件數(shù)據(jù)不至于失效,如下圖所示:
圖4.snapshot文件遷移
快照中還有一個命令就是clone_snapshot, 這個命令也很用,我們可以用它來重命名表,恢復(fù)表數(shù)據(jù)等。具體用法如下:
- hbase> clone_snapshot 'snapshot_src_table' , 'new_table_name'
這個命令也是不涉及實(shí)際數(shù)據(jù)文件的拷貝,所以執(zhí)行起來很快,那拷貝的是什么呢,與上面提到的引用文件不同,它所生成的是linkfile,這個文件不包含任何內(nèi)容,和上面引用文件一樣的是,在發(fā)生compact等操作時,會將原文件copy到/hbase/.archive目錄。
比如我們有一個表test, 有一個region原表信息如下:
- hbaseuser:~> hadoop fs -ls /hbase/data/default/test/d8340c61f5d77345b7fa55e0dfa9b492/*
- Found 1 items
- -rw-r--r-- 1 hbaseuser supergroup 37 2017-12-01 11:44 /hbase/data/default/test/d8340c61f5d77345b7fa55e0dfa9b492/.regioninfo
- Found 1 items
- -rw-r--r-- 1 hbaseuser supergroup 983 2017-12-01 12:13 /hbase/data/default/test/d8340c61f5d77345b7fa55e0dfa9b492/i/55c5de40f58f4d07aed767c5d250191
在創(chuàng)建一個snapshot之后:snapshot 'test', 'snapshot_test',在/hbase/.hbase-snapshot目錄信息如下:
- hbaseuser~> hadoop fs -ls /hbase/.hbase-snapshot/snapshot_test
- Found 4 items
- -rw-r--r-- 1 hbaseuser supergroup 32 2017-12-01 12:13 /hbase/.hbase-snapshot/snapshot_test/.snapshotinfo
- drwxr-xr-x - hbaseuser supergroup 0 2017-12-01 12:13 /hbase/.hbase-snapshot/snapshot_test/.tabledesc
- drwxr-xr-x - hbaseuser supergroup 0 2017-12-01 12:13 /hbase/.hbase-snapshot/snapshot_test/.tmp
- drwxr-xr-x - hbaseuser supergroup 0 2017-12-01 12:13 /hbase/.hbase-snapshot/snapshot_test/d8340c61f5d77345b7fa55e0dfa9b492
在clone_snapshot之后:clone_snapshot 'snapshot_test','new_test',在/hbase/archive/data/default目錄,有對原表的link目錄,目錄名只是在原HFile的文件名基礎(chǔ)上加了個links-前綴,這樣我們可以通過這個來定位到原表的HFile,如下所示:
- hbaseuser:~> hadoop fs -ls /hbase/archive/data/default/test/d8340c61f5d77345b7fa55e0dfa9b492/i
- Found 1 items
- drwxr-xr-x - hbaseuser supergroup 0 2017-12-01 12:34 /hbase/archive/data/default/test/d8340c61f5d77345b7fa55e0dfa9b492/i/.links-55c5de40f58f4d07
此時,再執(zhí)行合并操作:major_compact 'new_test',會發(fā)現(xiàn)/hbase/archive/data/default/目錄已經(jīng)變成了實(shí)際表的數(shù)據(jù)文件,上面圖中/hbase/archive/data/default/test/d8340c61f5d77345b7fa55e0dfa9b492/i/.links-55c5de40f58f4d07這個已經(jīng)不在了,取而代之的是如下所示文件:
- hbaseuser:~> hadoop fs -ls /hbase/archive/data/default/new_test/7e8636a768cd0c6141a3bb45b4098910/i
- Found 1 items
- -rw-r--r-- 1 hbaseuser supergroup 0 2017-12-01 12:48 /hbase/archive/data/default/new_test/7e8636a768cd0c6141a3bb45b4098910/i/test=d8340c61f5d77345b7fa55e0dfa9b492-55c5de40f58f4d07aed767c5d250191c
在實(shí)際的/hbase/data/default/new_test目錄也是實(shí)際的原表的數(shù)據(jù)文件,這樣完成了表數(shù)據(jù)的遷移。
3.3.3 snapshot數(shù)據(jù)遷移
snapshot的應(yīng)用場景和上面CopyTable描述差不多,我們這里主要考慮的是數(shù)據(jù)遷移部分。數(shù)據(jù)遷移主要有以下幾個步驟:
A.創(chuàng)建快照:在原集群上,用snapshot命令創(chuàng)建快照,命令如下:
- hbase> snapshot 'src_table', 'snapshot_src_table'
- #查看創(chuàng)建的快照,可用list_snapshots命令
- hbase> list_snapshots
- #如果快照創(chuàng)建有問題,可以先刪除,用delete_snapshot命令
- hbase >delete_snapshot 'snapshot_src_table'
創(chuàng)建完快照后在/hbase根目錄會產(chǎn)生一個目錄:
- /hbase/.hbase-snapshot/snapshot_src_table
- #子目錄下有如下幾個文件
- /hbase/.hbase-snapshot/snapshot_src_table/.snapshotinfo
- /hbase/.hbase-snapshot/snapshot_src_table/data.manifest
B.數(shù)據(jù)遷移: 在上面創(chuàng)建好快照后,使用ExportSnapshot命令進(jìn)行數(shù)據(jù)遷移,ExportSnapshot也是HDFS層的操作,本質(zhì)還是利用MR進(jìn)行遷移,這個過程主要涉及IO操作并消耗網(wǎng)絡(luò)帶寬,在遷移時要指定下map數(shù)和帶寬,不然容易造成機(jī)房其它業(yè)務(wù)問題,如果是單獨(dú)的MR集群,可以在MR集群上使用如下命令:
- hbase org.apache.hadoop.hbase.snapshot.ExportSnapshot \
- -snapshot snapshot_src_table \
- -copy-from hdfs://src-hbase-root-dir/hbase \
- -copy-to hdfs://dst-hbase-root-dir/hbase \
- -mappers 20 \
- -bandwidth 20
上面這些流程網(wǎng)上很多資料都有提到,對于我們業(yè)務(wù)來說,還有一種場景是要同步的表是正在實(shí)時寫的,雖然用上面的也可以解決,但考慮到我們表數(shù)據(jù)規(guī)模很大,幾十個T級別,同時又有實(shí)時業(yè)務(wù)在查的情況下,直接在原表上就算只是拷貝HFile,也會影響原集群機(jī)器性能,由于我們機(jī)器性能IO/內(nèi)存方面本身就比較差,很容易導(dǎo)致機(jī)器異常,所以我們采用的其它一種方案,流程圖如下:
圖5.新的snapshot遷移方案
為什么要采用這種方案呢,主要考慮的是直接對原表snapshot進(jìn)行Export會影響集群性能,所以采用折中的方案,即先把老表clone成一個新表,再對新表進(jìn)行遷移,這樣可以避免直接對原表操作。
四、總結(jié)
上文把HBase數(shù)據(jù)遷移過程中常用的一些方法作了一個大概介紹,總結(jié)起來就四點(diǎn):
DistCp: 文件層的數(shù)據(jù)同步,也是我們常用的
CopyTable: 這個涉及對原表數(shù)據(jù)Scan,然后直接Put到目標(biāo)表,效率較低
Export/Import: 類似CopyTable, Scan出數(shù)據(jù)放到文件,再把文件傳輸?shù)侥繕?biāo)集群作Import
Snapshot: 比較常用 , 應(yīng)用靈活,采用快照技術(shù),效率比較高
具體應(yīng)用時,要結(jié)合自身表的特性,考慮數(shù)據(jù)規(guī)模、數(shù)據(jù)讀寫方式、實(shí)時數(shù)據(jù)&離線數(shù)據(jù)等方面,再選擇使用哪種。