HBase数据迁移⽅案介绍
⼀、前⾔
HBase数据迁移是很常见的操作,⽬前业界主要的迁移⽅式主要分为以下⼏类:
![1]
图1.HBase数据迁移⽅案
从上⾯图中可看出,⽬前的⽅案主要有四类,Hadoop层有⼀类,HBase层有三类。下⾯分别介绍⼀下。
⼆、Hadoop层数据迁移
2.1 ⽅案介绍
Hadoop层的数据迁移主要⽤到DistCp(Distributed Copy),官⽅描述是:DistCp(分布式拷贝)是⽤于⼤规模集内部和集之间拷贝的⼯具。它使⽤Map/Reduce实现⽂件分发,错误处理
和恢复,以及报告⽣成。它把⽂件和⽬录的列表作为map任务的输⼊,每个任务会完成源列表中部分⽂件的拷贝。
我们知道MR程序适合⽤来处理⼤批量数据,其拷贝本质过程是启动⼀个MR作业,不过DisctCp只有map,没有reducer。在拷贝时,由于要保证⽂件块的有序性,转换的最⼩粒度是⼀个⽂
件,⽽不像其它MR作业⼀样可以把⽂件拆分成多个块启动多个map并⾏处理。如果同时要拷贝多个⽂件,DisctCp会将⽂件分配给多个map,每个⽂件单独⼀个map任务。我们可以在执⾏
同步时指定-m参数来设定要跑的map数量,默认设置是20。如果是集间的数据同步,还需要考虑带宽问题,所以在跑任务时还需要设定 bandwitdh 参数,以防⽌⼀次同步过多的⽂件造成
带宽过⾼影响其它业务。同时,由于我们HBase集⼀般是不会开MR调度的,所以这⾥还需要⽤到单独的MR集来作主备数据同步,即在跑任务时还需要指定mapreduce相关参数。
简单的distcp参数形式如下:
hadoop distcp hdfs://src-hadoop-address:9000/table_name hdfs://dst-hadoop-address:9000/table_name
如果是独⽴的MR集来执⾏distcp,因为数据量很⼤,⼀般是按region⽬录粒度来传输,同时传输到⽬标集时,我们先把⽂件传到临时⽬录,最后再⽬的集上load表,我们⽤到的形式如
下:
hadoop distcp \
-Dmapreduce.job.name=distcphbase \
-sourcemanager.webapp.address=mr-master-ip:8088 \
-source-tracker.address=mr-master-dns:8093 \
-sourcemanager.scheduler.address=mr-master-dns:8091 \
-sourcemanager.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 ⽅案实施
迁移⽅法如下:
第⼀步,如果是迁移实时写的表,最好是停⽌集对表的写⼊,迁移历史表的话就不⽤了,此处举例表名为test;
第⼆步, flush表,打开HBase Shell客户端,执⾏如下命令:
hbase> flush 'test'
第三步,拷贝表⽂件到⽬的路径,检查源集到⽬标集策略、版本等,确认没问题后,执⾏如上带M
R参数的命令
第四步,检查⽬标集表是否存在,如果不存在需要创建与原集相同的表结构
第五步,在⽬标集上,Load表到线上,在官⽅Load是执⾏如下命令:
hbase org.jruby.Main add_table.rb /hbase/data/default/test
对于我们来说,因我们先把⽂件同步到了临时⽬录,并不在原表⽬录,所以我们采⽤的另⼀种形式的load,即以region的维度来Load数据到线上表,怎么做呢,这⾥⽤到的是
org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles这个类,即以bulkload的形式来load数据。上⾯同步时我们将⽂件同步到了⽬的集的/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
这⾥还⽤到⼀个参数hbase.mapreduce.bulkload.max.hfiles.perRegion.perFamily, 这个表⽰在bulkload过程中,每个region列族的HFile数的上限,这⾥我们是限定了1024,也可以指定更少,
根据实际需求来定。
第六步,检查表数据是否OK,看bulkload过程是否有报错
在同步过程中,我们为加块同步速度,还会开个多线程来并发同步⽂件,这个可根据实际数据量和⽂件数来决定是否需要使⽤并发同步。
三、HBase层数据迁移
3.1 copyTable⽅式
copyTable也是属于HBase数据迁移的⼯具之⼀,以表级别进⾏数据迁移。copyTable的本质也是利⽤MapReduce进⾏同步的,与DistCp不同的时,它是利⽤MR去scan 原表的数据,然后把
scan出来的数据写⼊到⽬标集的表。这种⽅式也有很多局限,如⼀个表数据量达到T级,同时⼜在读写的情况下,全量scan表⽆疑会对集性能造成影响。
来看下copyTable的⼀些使⽤参数:
Usage: CopyTable [general options] [--starttime=X] [--endtime=Y] [--new.name=NEW] [--peer.adr=ADR] <tablename>
Options:
rs.class ionserver.class of the peer cluster
specify if different from current cluster
rs.impl ionserver.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
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"
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.ution=false
从上⾯参数,可以看出,copyTable⽀持设定需要复制的表的时间范围,cell的版本,也可以指定列簇,设定从集的地址,起始/结束⾏键等。参数还是很灵活的。copyTable⽀持如下⼏个
场景:
1.表深度拷贝:相当于⼀个快照,不过这个快照是包含原表实际数据的,0.94.x版本之前是不⽀持snapshot快照命令的,所以⽤copyTable相当于可以实现对原表的拷贝,使⽤⽅式如下:
create 'table_snapshot',{NAME=>"i"}
hbase org.apache.hadoop.hbase.mapreduce.CopyTable --new.name=tableCopy table_snapshot
2.集间拷贝:在集之间以表维度同步⼀个表数据,使⽤⽅式如下:
create 'table_test',{NAME=>"i"} #⽬的集上先创建⼀个与原表结构相同的表
hbase org.apache.hadoop.hbase.mapreduce.CopyTable --peer.adr=zk-addr1,zk-addr2,zk-addr3:2181:/hbase table_test
3.增量备份:增量备份表数据,参数中⽀持timeRange,指定要备份的时间范围,使⽤⽅式如下:
hbase org.apache.hadoop.hbase.mapreduce.CopyTable ... --starttime=start_timestamp --endtime=end_timestamp
4.部分表备份:只备份其中某⼏个列族数据,⽐如⼀个表有很多列族,但我只想备份其中⼏个列族数据,CopyTable提供了families参数,同时还提供了copy列族到新列族形式,使⽤⽅式如
下:
hbase org.apache.hadoop.hbase.mapreduce.CopyTable ... --families=srcCf1,srcCf2 #copy cf1,cf2两个列族,不改变列族名字
hbase属于什么数据库hbase org.apache.hadoop.hbase.mapreduce.CopyTable ... --families=srcCf1:dstCf1, srcCf2:dstCf2 #copy srcCf1到⽬标dstCf1新列族
总的来说,CopyTable⽀持的范围还是很多的,但因其涉及的是直接HBase层数据的拷贝,所以效率上会很低,同样需要在使⽤过程中限定扫描原表的速度和传输的带宽,这个⼯具实际上
使⽤⽐较少,因为很难控制。
3.2 Export/Import⽅式
此⽅式与CopyTable类似,主要是将HBase表数据转换成Sequence File并dump到HDFS,也涉及Scan表数据,与CopyTable相⽐,还多⽀持不同版本数据的拷贝,同时它拷贝时不是将
HBase数据直接Put到⽬标集表,⽽是先转换成⽂件,把⽂件同步到⽬标集后再通过Import到线上表。主要有两个阶段:
Export阶段: 将原集表数据Scan并转换成Sequence File到Hdfs上,因Export也是依赖于MR的,如果⽤到独⽴的MR集的话,只要保证在MR集上关于HBase的配置和原集⼀样且能和
原集策略打通(master®ionserver策略),就可直接⽤Export命令,如果没有独⽴MR集,则只能在HBase集上开MR,若需要同步多个版本数据,可以指定versions参数,否则默认
同步最新版本的数据,还可以指定数据起始结束时间,使⽤如下:
# output_hdfs_path可以直接是⽬标集的hdfs路径,也可以是原集的HDFS路径,如果需要指定版本号,起始结束时间
hbase org.apache.hadoop.hbase.mapreduce.Export <tableName> <ouput_hdfs_path> <versions> <starttime> <endtime>
Import阶段: 将原集Export出的SequenceFile导到⽬标集对应表,使⽤如下:
#如果原数据是存在原集HDFS,此处input_hdfs_path可以是原集的HDFS路径,如果原数据存在⽬标集HDFS,则为⽬标集的HDFS路径
hbase org.apache.hadoop.hbase.mapreduce.Import <tableName> <input_hdfs_path>
3.3 Snapshot⽅式
3.3.1 snapshot介绍
此⽅式与上⾯⼏中⽅式有所区别,也是⽬前⽤得⽐较多的⽅案,snapshot字⾯意思即快照,传统关系型数据库也有快照的概念,HBase中关于快照的概念定义如下:
快照就是⼀份元信息的合集,允许管理员恢复到表的先前状态,快照不是表的复制⽽是⼀个⽂件名称列表,因⽽不会复制数据
因不拷贝实际的数据,所以整个过程是⽐较快的,相当于对表当前元数据状态作⼀个克隆,snapshot的流程主要有三个步骤:
![2]
图2.数据迁移图
加锁: 加锁对象是regionserver的memstore,⽬的是禁⽌在创建snapshot过程中对数据进⾏insert,update,delete操作
刷盘:刷盘是针对当前还在memstore中的数据刷到HDFS上,保证快照数据相对完整,此步也不是强制的,如果不刷会,快照中数据有不⼀致风险
创建指针: snapshot过程不拷贝数据,但会创建对HDFS⽂件的指针,snapshot中存储的就是这些指标元数据
3.3.2 snapshot内部原理
snapshot实际内部是怎么做的呢,上⾯说到,snapshot只是对元数据信息克隆,不拷贝实际数据⽂件,我们以表test为例,这个表有三个region, 每个region分别有两个HFile,创建snapshot
过程如下:
![3]
图3.snapshot创建内部原理
创建的snapshot放在⽬录/hbase/.hbase-snapshot/下,元数据信息放在/hbase/.hbase-snapshot/data.manifest中,如上图所⽰,snapshot中也分别包含对原表region HFile的引⽤,元数据信
息具体包括哪哪些呢:
1. snapshot元数据信息
2. 表的元数据信息&schema,即原表的.tableinfo⽂件
3. 对原表Hfile的引⽤信息
由于我们表的数据在实时变化,涉及region的Hfile合并删除等操作,对于snapshot⽽⾔,这部分数据HB
ase会怎么处理呢,实际上,当发现spit/compact等操作时,HBase会将原表发⽣变化
的HFile拷贝到/hbase/.archive⽬录,如上图中如果Region3的F31&F32发⽣变化,则F31和F32会被同步到.archive⽬录,这样发⽣修改的⽂件数据不⾄于失效,如下图所⽰:
![4]
图4.snapshot⽂件迁移
快照中还有⼀个命令就是clone_snapshot,这个命令也很⽤,我们可以⽤它来重命名表,恢复表数据等。具体⽤法如下:
hbase> clone_snapshot 'snapshot_src_table' , 'new_table_name'
这个命令也是不涉及实际数据⽂件的拷贝,所以执⾏起来很快,那拷贝的是什么呢,与上⾯提到的引⽤⽂件不同,它所⽣成的是linkfile,这个⽂件不包含任何内容,和上⾯引⽤⽂件⼀样的
是,在发⽣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
在创建⼀个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的⽂件名基础上加了个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
此时,再执⾏合并操作:major_compact 'new_test',会发现 /hbase/archive/data/default/⽬录已经变成了实际表的数据⽂件,上⾯图
中/hbase/archive/data/default/test/d8340c61f5d77345b7fa55e0dfa9b492/i/.links-55c5de40f58f4d07这个已经不在了,取⽽代之的是如下所⽰⽂件:
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-55c5de40f58f4d07aed767c5d25019在实际的/hbase/data/default/new_test⽬录也是实际的原表的数据⽂件,这样完成了表数据的迁移。
3.3.3 snapshot数据迁移
snapshot的应⽤场景和上⾯CopyTable描述差不多,我们这⾥主要考虑的是数据迁移部分。数据迁移主要有以下⼏个步骤:
A.创建快照:在原集上,⽤snapshot命令创建快照,命令如下:
hbase> snapshot 'src_table', 'snapshot_src_table'
#查看创建的快照,可⽤list_snapshots命令
hbase> list_snapshots
#如果快照创建有问题,可以先删除,⽤delete_snapshot命令
hbase >delete_snapshot 'snapshot_src_table'
创建完快照后在/hbase根⽬录会产⽣⼀个⽬录:
/hbase/.hbase-snapshot/snapshot_src_table
#⼦⽬录下有如下⼏个⽂件
/hbase/.hbase-snapshot/snapshot_src_table/.snapshotinfo
/hbase/.hbase-snapshot/snapshot_src_table/data.manifest
B.数据迁移: 在上⾯创建好快照后,使⽤ExportSnapshot命令进⾏数据迁移,ExportSnapshot也是HDFS层的操作,本质还是利⽤MR进⾏迁移,这个过程主要涉及IO操作并消耗⽹络带宽,
在迁移时要指定下map数和带宽,不然容易造成机房其它业务问题,如果是单独的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
上⾯这些流程⽹上很多资料都有提到,对于我们业务来说,还有⼀种场景是要同步的表是正在实时写的,虽然⽤上⾯的也可以解决,但考虑到我们表数据规模很⼤,⼏⼗个T级别,同时⼜有
实时业务在查的情况下,直接在原表上就算只是拷贝HFile,也会影响原集机器性能,由于我们机器性能IO/内存⽅⾯本⾝就⽐较差,很容易导致机器异常,所以我们采⽤的其它⼀种⽅案,
流程图如下:
![5]
图5.新的snapshot迁移⽅案
为什么要采⽤这种⽅案呢,主要考虑的是直接对原表snapshot进⾏Export会影响集性能,所以采⽤折中的⽅案,即先把⽼表clone成⼀个新表,再对新表进⾏迁移,这样可以避免直接对原
表操作。
四、总结
上⽂把HBase数据迁移过程中常⽤的⼀些⽅法作了⼀个⼤概介绍,总结起来就四点:
DistCp: ⽂件层的数据同步,也是我们常⽤的
CopyTable: 这个涉及对原表数据Scan,然后直接Put到⽬标表,效率较低
Export/Import: 类似CopyTable, Scan出数据放到⽂件,再把⽂件传输到⽬标集作Import
Snapshot: ⽐较常⽤,应⽤灵活,采⽤快照技术,效率⽐较⾼
具体应⽤时,要结合⾃⾝表的特性,考虑数据规模、数据读写⽅式、实时数据&离线数据等⽅⾯,再选择使⽤哪种。
参考:
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论