目前的方案主要有四类,Hadoop层有一类,HBase层有三类,这里使用后SnapShot方式迁移HBase
SnapShot方式迁移HBase:
也是目前用得比较多的方案,snapshot字面意思即快照, 传统关系型数据库也有快照的概念,HBase中关于快照的概念定义如下:
快照就是一份元信息的合集,允许管理员恢复到表的先前状态,快照不是表的复制而是一个文件名称列表,因而不会复制数据。
因不拷贝实际的数据,所以整个过程是比较快的,相当于对表当前元数据状态作一个克隆,snapshot的流程主要有三个步骤:
- 加锁: 加锁对象是regionserver的memstore,目的是禁止在创建snapshot过程中对数据进行insert,update,delete操作
- 刷盘:刷盘是针对当前还在memstore中的数据刷到HDFS上,保证快照数据相对完整,此步也不是强制的,如果不刷会,快照中数据有不一致风险
- 创建指针: snapshot过程不拷贝数据,但会创建对HDFS文件的指针,snapshot中存储的就是这些指标元数据
snapshot只是对元数据信息克隆,不拷贝实际数据文件,我们以表test为例,这个表有三个region, 每个region分别有两个HFile,创建snapshot过程如下:
创建的snapshot放在目录/hbase/.hbase-snapshot/下, 元数据信息放在/hbase/.hbase-snapshot/data.manifest中, 如上图所示,snapshot中也分别包含对原表region HFile的引用,元数据信息具体包括:
- snapshot元数据信息
- 表的元数据信息&schema,即原表的.tableinfo文件
- 对原表Hfile的引用信息
由于我们表的数据在实时变化,涉及region的Hfile合并删除等操作,对于snapshot而言,这部分数据HBase会怎么处理呢,实际上,当发现spit/compact等操作时,HBase会将原表发生变化的HFile拷贝到/hbase/.archive目录,如上图中如果Region3的F31&F32发生变化,则F31和F32会被同步到.archive目录,这样发生修改的文件数据不至于失效,如下图所示:
快照中还有一个命令就是clone_snapshot, 这个命令也很用,我们可以用它来重命名表,恢复表数据等。具体用法如下:
hbase(main):001:0> clone_snapshot 'snapshot_src_table' , 'new_table_name'
这个命令也是不涉及实际数据文件的拷贝,所以执行起来很快,那拷贝的是什么呢,与上面提到的引用文件不同,它所生成的是linkfile,这个文件不包含任何内容,和上面引用文件一样的是,在发生compact等操作时,会将原文件copy到/hbase/.archive目录。
比如我们有一个表test, 有一个region原表信息如下:
比如我创建一个表t1,并创建为其快照t1snap。然后再克隆成newt1snap
# hdfs dfs -ls /data/hbase/tmp/hbase/data/default/t1/fda2cb87dafb17b42a1fa67e0f9c4484/*
Found 1 items
-rwxr-xr-x 2 root supergroup 35 2019-01-25 16:53 /data/hbase/tmp/hbase/data/default/t1/fda2cb87dafb17b42a1fa67e0f9c4484/.regioninfo
Found 1 items
-rwxr-xr-x 2 root supergroup 1060 2019-01-25 16:53 /data/hbase/tmp/hbase/data/default/t1/fda2cb87dafb17b42a1fa67e0f9c4484/tab_add/18248d4491574f3785bbd81e4b4b4c8a
在创建一个snapshot之后:snapshot 't1', 't1snap',在/hbase/.hbase-snapshot目录信息如下:
# hdfs dfs -ls /data/hbase/tmp/hbase/.hbase-snapshot/t1snap
Found 4 items
-rwxr-xr-x 2 root supergroup 23 2019-01-25 16:53 /data/hbase/tmp/hbase/.hbase-snapshot/t1snap/.snapshotinfo
drwxr-xr-x - root supergroup 0 2019-01-25 16:53 /data/hbase/tmp/hbase/.hbase-snapshot/t1snap/.tabledesc
drwxr-xr-x - root supergroup 0 2019-01-25 16:53 /data/hbase/tmp/hbase/.hbase-snapshot/t1snap/.tmp
drwxr-xr-x - root supergroup 0 2019-01-25 16:53 /data/hbase/tmp/hbase/.hbase-snapshot/t1snap/fda2cb87dafb17b42a1fa67e0f9c4484
在clone_snapshot之后:clone_snapshot 't1snap','newt1snap',在/hbase/archive/data/default目录,有对原表的link目录,目录名只是在原HFile的文件名基础上加了个links-前缀,这样我们可以通过这个来定位到原表的HFile,如下所示:
# hdfs dfs -ls /data/hbase/tmp/hbase/archive/data/default/t1/fda2cb87dafb17b42a1fa67e0f9c4484/tab_add
Found 1 items
drwxr-xr-x - root supergroup 0 2019-01-29 09:57 /data/hbase/tmp/hbase/archive/data/default/t1/fda2cb87dafb17b42a1fa67e0f9c4484/tab_add/.links-18248d4491574f3785bbd81e4b4b4c8a
此时,再执行合并操作:major_compact 'newt1snap',会发现/hbase/archive/data/default/目录已经变成了实际表的数据文件,上面图中/data/hbase/tmp/hbase/archive/data/default/t1/fda2cb87dafb17b42a1fa67e0f9c4484/tab_add这个已经不在了,取而代之的是如下所示文件:
# hdfs dfs -ls /data/hbase/tmp/hbase/archive/data/default/newt1snap/3d096ea2fa1a330aba9c2675b35ec375/tab_add
Found 1 items
-rw-r--r-- 2 root supergroup 0 2019-01-29 10:04 /data/hbase/tmp/hbase/archive/data/default/newt1snap/3d096ea2fa1a330aba9c2675b35ec375/tab_add/t1=fda2cb87dafb17b42a1fa67e0f9c4484-18248d4491574f3785bbd81e4b4b4c8a
在实际的/data/hbase/tmp/hbase/data/default/newt1snap目录也是实际的原表的数据文件,这样完成了表数据的迁移。
前期准备
确认集群使用的版本
源HBase集群(以下称旧集群)和目的HBase集群(以下称新集群)的版本可能并不是一致的,特别是其底层所使用的HDFS版本信息。譬如这样一个数据迁移场景:业务希望从低版本的HBase集群(0.96.x)迁移到当前稳定的HBase集群(1.2.x),因为新版本的HBase有新特性,Bug更少,稳定性和可运维行更优。理论上新版本会兼容老版本的API,但是如果彼此版本差距过大,可能会出现HDFS RPC版本不一致(一般来说是Protobuf的版本),那么集群之间的迁移就会因为彼此与对方的NameNode无法进行通信而无法进行。 这种情况下,需要先考虑升级低版本的HDFS。
确认集群是否开启Kerberos认证
这里会有三种可能情况:一是都未开启认证,二是都开启认证,三是一个开了,另一个没开。前两种情况按照正常的认证(或非认证)的配置操作即可,第三种情况则需要在开启了认证的集群上开启 ipc.client.fallback-to-simple-auth-allowed 参数,意即在使用Kerberos的方式访问非Kerberos的集群时,系统自动转换成简单认证,否则会出现认证问题。Kerberos的配置和使用本文不做展开。
确认操作账号的读写权限问题
要在不同的HBase集群之间做数据迁移,必然要涉及到不同集群的读写权限问题。HBase使用ACL来管理不同数据表的读写权限,在开启了Kerberos认证的环境下,还需要验证Kerberos;而HBase使用的HDFS自身也有一套类似的权限管理规则,当两个集群配置不同时(如部署账号不一致),极易出现冲突。在迁移前需要确认两个集群的管理员账号(HDFS和HBase账号)是否一致,如果不一致,需要开通权限。
开启YARN服务
数据迁移任务本质上是一个MapRedcue任务,故需要在一个集群上开启YARN服务。如何选择在哪个集群上开呢?建议是在新集群上开,因为旧集群上可能还需要继续跑线上业务,在上面起大量Map任务并把数据远程写入到新集群,会对线上业务带来较大的性能影响;而新集群较大可能是一个独立集群,尚没有业务运行,在其上运行Map任务通过网络从旧集群中拉数据到本地写入,性价比更高,且对线上业务的侵入性更低。
在HBase集群上配置YARN服务可以查阅其安装部署文档,这里不做展开。
确认数据迁移的SLA
数据迁移是否是在线迁移,即业务不能中断。若业务允许做离线迁移,可以先将该表Disable后再做迁移,然后在新集群上重新clone成新表即可;但若需要在线进行迁移,则需要提前新集群上生成对应的HBase表,开启ACL权限等操作,并让业务开启数据双写,确保两个集群的数据在迁移时刻之后的数据是一致的。因为数据迁移和后续的数据合并耗时都很长,如果不开启双写,是无法达到数据一致性要求的。所以大多数情况下,业务都是要求数据迁移以在线方式进行。
源集群开启Snapshot
HBase的Snapshot是从0.94.6之后才引入的特性,开启Snapshot特性需要开启 hbase.snapshot.enabled (默认已开启)。如果没有开启该特性,则需要重启服务以开启该特性;如果版本过低,就只能使用其他对业务影响较大的CopyTable/ExportTable(需要Disable表)才能操作。
生成HBase表和Region
完成前期的验证和准备工作后,就可以在新集群中创建待迁移的目的表和域(以下称Region)了。 因为迁移过程中业务需要开启双写,所以目的表结构必须和源表是一致;同时源数据表可能已经存在多个Region了,那么目的表也必须提前规划好这些Region,以免双写期间出现Region数量不足出现热点或者Region内文件数过多频繁Compact导致线上业务出现性能问题。 这里详细说明下如何正确创建一个带有多个Region的表。
迁移流程设计
对于业务级别的HBase数据迁移,HBase需要迁移的表是在实时写入的。当数据规模达到T级别是,同时又在有实时业务在查的情况下,直接在生产表上操作,就算是只拷贝Hfile,也会影响到原集群的机器性能,容易产生意外。
主要考虑的是直接对原表snapshot进行Export会影响集群性能,所以采用折中的方案,即先把老表clone成一个新表,再对新表进行迁移,这样可以避免直接对原表操作。所以采用如下流程:
开始
⬇
在原集群创建快照
snapshot 'tablename', 'snapshotname'
⬇
在原集群克隆快照
clone_snapshot 'snapshotname', 'newtablename'
⬇
在原集群合并新表
major_compact 'newtablename'
⬇
在目标集群进行迁移
hadoop distcp -i hftp://destnation:port/
⬇
在目标集群修复表
hbase hbck -repair OR hbase hbck -fixAssignments -fixMeta
major_compact的时机
major_compact是很重的后台操作。因此操作之前需要有仔细的观察和分析(通过grafana->HBase监控可以获得):
- 业务低峰时段运行;
- 优先考虑含有TTL的表;
- storefile短期内增加比较多;
- 表中storefile平均大小比较小;
本题采用hadoop DisCp的方式实现数据迁徙
DistCp(Distributed Copy)是用于大规模集群内部或者集群之间的高性能拷贝工具。 它使用Map/Reduce实现文件分发,错误处理和恢复,以及报告生成。 它把文件和目录的列表作为map任务的输入,每个任务会完成源列表中部分文件的拷贝。
DistCp是Apache Hadoop自带的工具,目前存在两个版本,DistCp1和DistCp2,FastCopy是Facebook Hadoop中自带的,相比于Distcp,它能明显加快同节点数据拷贝速度,尤其是Hadoop 2.0稳定版(第一个稳定版为2.2.0,该版本包含的特性可参考我的这篇文章:Hadoop 2.0稳定版本2.2.0新特性剖析)发布后,当需要在不同NameNode间(HDFS Federation)迁移数据时,FastCopy将发挥它的最大用武之地。
DistCp第一版使用了MapReduce并发拷贝数据,它将整个数据拷贝过程转化为一个map-only Job以加快拷贝速度。由于DistCp本质上是一个MapReduce作业,它需要保证文件中各个block的有序性,因此它的最小数据切分粒度是文件,也就是说,一个文件不能被切分成不同部分让多个任务并行拷贝,最小只能做到一个文件交给一个任务。
DistCp2针对DistCp1在易用性和性能等方面的不足,提出了一系列改进点,包括通过去掉不必要的检查缩短了目录扫描时间、动态分配各个Map Task的数据量、可对拷贝限速避免占用过多网络流量、支持HSFTP等。尤其值得一说的是动态分配Map Task处理数据量。DistCp1的实现跟我们平时写的大部分MapReduce程序一样,每个Map Task的待处理数据量在作业开始运行前已经静态分配好了,这就出现了我们经常看到的拖后腿的现象:由于一个Map Task分配的数据量过多,运行非常缓慢,所有Reduce Task都在等待这个Map Task运行完成。而对于DistCp而言,该现象更加常见,因为最小的数据划分单位是文件,文件有大有小,分到大文件的Map Task将运行的非常慢,比如你有两个待拷贝的文件,一个大小为1GB,另一个大小为1TB,如果你指定了超过2个的Map Task,则该DistCp只会启动两个Map Task,其中一个负责拷贝1GB的文件,另一个负责拷贝1TB的文件,可以想象其中一个任务将运行的非常慢。DistCp2通过动态分配Map Task数据量解决了该问题,它实现了一个DynamicInputFormat,该InputFormat将待拷贝的目录文件分解成很多的chunk,其中每个chunk的信息(位置,文件名等)写到一个以“.chunk.K”(K是一个数字)结尾的HDFS文件中,这样,每个文件可看做一份“任务”,“任务”数目要远大于启动的Map Task数目,运行快的Map Task能够多领取一些“任务”,而运行慢得则领取少一些,进而提高数据拷贝速度。尽管DistCp1中Map Task拷贝数据最小单位仍是文件,但相比于DistCp1,则要高效得多,尤其是在文件数据庞大,且大小差距较大的情况下。
创建好快照后,使用ExportSnapshot命令进行数据迁移,ExportSnapshot也是HDFS层的操作,本质还是利用MR进行迁移,这个过程主要涉及IO操作并消耗网络带宽,在迁移时要指定下map数和带宽,不然容易造成机房其它业务问题。
考虑到本次迁移是不同版本之间的数据迁移,含hdfs数据迁移,
如果想在两个运行着不同版本HDFS的集群上利用distcp,使用hdfs协议是会失败的,因为RPC系统是不兼容的。想要弥补这种情况,可以使用基于HTTP的HFTP或者是基于FTP的HFTP文件系统从源中进行读取。这个作业必须运行在目标集群上,使得HDFS RPC版本是兼容的。
distcp命令介绍:
非常重要须知事项:
distcp之前必须将source hbase集群的hosts文件同步至目标集群的/etc/hosts,否则会报:UnknownHostException: .local的错误。此故障会导致拷贝过程中数据丢失的情况,或者无法拷贝的情况。
选项索引
标识
描述
备注
-p[rbugp]
Preserve
r: replication number
b: block size
u: user
g: group
p: permission
修改次数不会被保留。并且当指定 -update 时,更新的状态不会 被同步,除非文件大小不同(比如文件被重新创建)。
-i
忽略失败
就像在 附录中提到的,这个选项会比默认情况提供关于拷贝的更精确的统计, 同时它还将保留失败拷贝操作的日志,这些日志信息可以用于调试。最后,如果一个map失败了,但并没完成所有分块任务的尝试,这不会导致整个作业的失败。这个选项会忽略失败信息,慎用。troubleshooting时删掉。
-log
记录日志到
DistCp为每个文件的每次尝试拷贝操作都记录日志,并把日志作为map的输出。 如果一个map失败了,当重新执行时这个日志不会被保留。
-m
同时拷贝的最大数目
指定了拷贝数据时map的数目。请注意并不是map数越多吞吐量越大。
-overwrite
覆盖目标
如果一个map失败并且没有使用-i选项,不仅仅那些拷贝失败的文件,这个分块任务中的所有文件都会被重新拷贝。 就像下面提到的,它会改变生成目标路径的语义,所以 用户要小心使用这个选项。
-update
如果源和目标的大小不一样则进行覆盖
像之前提到的,这不是"同步"操作。 执行覆盖的唯一标准是源文件和目标文件大小是否相同;如果不同,则源文件替换目标文件。 像 下面提到的,它也改变生成目标路径的语义, 用户使用要小心。
-f
使用
这等价于把所有文件名列在命令行中。 urilist_uri 列表应该是完整合法的URI。
实机测试环境操作记录
原集群环境为CentOS-7.6_1810,测试集群,手动搭建hadoop+hbase双点集群。
源集群:192.168.40.181 jiajinyun-1 ||| 192.168.40.182 jiajinyun-2
jiajinyun-1为源集群namenode,hadoop版本:Hadoop 2.3.0-cdh5.0.6,hbase版本:HBase 0.96.2-hadoop2
目标集群环境为CentOS-7.6_1810,测试集群,Cloudera Manager双点集群,角色为hadoop与hbase。
目标集群:192.168.40.114 jiajinyun-6 ||| 192.168.40.116 jiajinyun-7
jiajinyun-6为目标集群namenode,hadoop版本:Hadoop 2.6.0-cdh5.15.1,hbase版本:HBase 1.2.0-cdh5.15.1
First.在原集群上创建快照
首先创建测试表t1:
# hbase shell
2019-01-25 15:01:27,868 INFO [main] Configuration.deprecation: hadoop.native.lib is deprecated. Instead, use io.native.lib.available
HBase Shell; enter 'help
Type "exit
Version 0.96.2-hadoop2, r1581096, Mon Mar 24 16:03:18 PDT 2014
hbase(main):003:0> version
0.96.2-hadoop2, r1581096, Mon Mar 24 16:03:18 PDT 2014
hbase(main):004:0> create 't1', 'tab_id', 'tab_add', 'tab_info'
0 row(s) in 0.5720 seconds
=> Hbase::Table - t1
hbase(main):005:0> list
TABLE
t1
t3
2 row(s) in 0.0380 seconds
=> ["t1", "t3"]
hbase(main):006:0> describe 't1'
DESCRIPTION ENABLED
't1', {NAME => 'tab_add', BLOOMFILTER => 'ROW', VERSIONS = true
> '1', IN_MEMORY => 'false', KEEP_DELETED_CELLS => 'false'
, DATA_BLOCK_ENCODING => 'NONE', TTL => '2147483647', COMP
RESSION => 'NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'tru
e', BLOCKSIZE => '65536', REPLICATION_SCOPE => '0'}, {NAME
=> 'tab_id', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_ME
MORY => 'false', KEEP_DELETED_CELLS => 'false', DATA_BLOCK
_ENCODING => 'NONE', TTL => '2147483647', COMPRESSION => '
NONE', MIN_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZ
E => '65536', REPLICATION_SCOPE => '0'}, {NAME => 'tab_inf
o', BLOOMFILTER => 'ROW', VERSIONS => '1', IN_MEMORY => 'f
alse', KEEP_DELETED_CELLS => 'false', DATA_BLOCK_ENCODING
=> 'NONE', TTL => '2147483647', COMPRESSION => 'NONE', MIN
_VERSIONS => '0', BLOCKCACHE => 'true', BLOCKSIZE => '6553
6', REPLICATION_SCOPE => '0'}
1 row(s) in 0.0410 seconds
hbase(main):009:0> put 't1', '1', 'tab_add:name', 'ninja'
0 row(s) in 0.0060 seconds
hbase(main):010:0> scan 't1'
ROW COLUMN+CELL
1 column=tab_add:name, timestamp=1548400348427, value=ninja
1 row(s) in 0.0180 seconds
hbase(main):011:0> put 't1', '1', 'tab_add:city', 'tokyo'
0 row(s) in 0.0070 seconds
hbase(main):012:0> scan 't1'
ROW COLUMN+CELL
1 column=tab_add:city, timestamp=1548400407062, value=tokyo
1 column=tab_add:name, timestamp=1548400348427, value=ninja
1 row(s) in 0.0100 seconds
创建快照:
hbase(main):016:0> snapshot 't1', 't1snap'
0 row(s) in 0.3940 seconds
查看快照:
hbase(main):017:0> list_snapshots
SNAPSHOT TABLE + CREATION TIME
t1snap t1 (Fri Jan 25 15:17:16 +0800 2019)
t3snap t3 (Fri Jan 25 11:13:13 +0800 2019)
2 row(s) in 0.1540 seconds
=> ["t1snap", "t3snap"]
删除快照:
hbase(main):018:0> delete_snapshot 't3snap'
0 row(s) in 0.0230 seconds
hbase(main):019:0> list_snapshots
SNAPSHOT TABLE + CREATION TIME
t1snap t1 (Fri Jan 25 15:17:16 +0800 2019)
1 row(s) in 0.0110 seconds
=> ["t1snap"]
退出HBase shell操作界面:
hdfs的HBase根目录hbase会产生以下文件目录:
# hdfs dfs -ls /data/hbase/tmp/hbase
19/01/25 17:02:44 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Found 9 items
drwxr-xr-x - root supergroup 0 2019-01-25 17:00 /data/hbase/tmp/hbase/.hbase-snapshot
drwxr-xr-x - root supergroup 0 2019-01-25 17:01 /data/hbase/tmp/hbase/.tmp
drwxr-xr-x - root supergroup 0 2019-01-25 17:01 /data/hbase/tmp/hbase/WALs
drwxr-xr-x - root supergroup 0 2019-01-25 16:57 /data/hbase/tmp/hbase/archive
drwxr-xr-x - root supergroup 0 2019-01-25 16:20 /data/hbase/tmp/hbase/corrupt
drwxr-xr-x - root supergroup 0 2019-01-24 11:43 /data/hbase/tmp/hbase/data
-rw-r--r-- 2 root supergroup 42 2019-01-24 11:43 /data/hbase/tmp/hbase/hbase.id
-rw-r--r-- 2 root supergroup 7 2019-01-24 11:43 /data/hbase/tmp/hbase/hbase.version
drwxr-xr-x - root supergroup 0 2019-01-25 16:59 /data/hbase/tmp/hbase/oldWALs
# hdfs dfs -ls /data/hbase/tmp/hbase.hbase-snapshot
19/01/25 17:03:34 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
ls: `/data/hbase/tmp/hbase.hbase-snapshot': No such file or directory
[root@jiajinyun-1 bin]# hdfs dfs -ls /data/hbase/tmp/hbase/.hbase-snapshot
19/01/25 17:03:37 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Found 1 items
drwxr-xr-x - root supergroup 0 2019-01-25 16:53 /data/hbase/tmp/hbase/.hbase-snapshot/t1snap
# hdfs dfs -ls /data/hbase/tmp/hbase/.hbase-snapshot/t1snap
19/01/25 17:05:33 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
Found 4 items
-rwxr-xr-x 2 root supergroup 23 2019-01-25 16:53 /data/hbase/tmp/hbase/.hbase-snapshot/t1snap/.snapshotinfo
drwxr-xr-x - root supergroup 0 2019-01-25 16:53 /data/hbase/tmp/hbase/.hbase-snapshot/t1snap/.tabledesc
drwxr-xr-x - root supergroup 0 2019-01-25 16:53 /data/hbase/tmp/hbase/.hbase-snapshot/t1snap/.tmp
drwxr-xr-x - root supergroup 0 2019-01-25 16:53 /data/hbase/tmp/hbase/.hbase-snapshot/t1snap/fda2cb87dafb17b42a1fa67e0f9c4484
# hbase shell
2019-01-25 17:09:59,329 INFO [main] Configuration.deprecation: hadoop.native.lib is deprecated. Instead, use io.native.lib.available
HBase Shell; enter 'help
Type "exit
Version 0.96.2-hadoop2, r1581096, Mon Mar 24 16:03:18 PDT 2014
Second.在原集群上克隆快照
hbase(main):002:0> clone_snapshot 't1snap', 'newt1snap'
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/usr/local/hbase/lib/slf4j-log4j12-1.6.4.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/usr/local/hadoop/share/hadoop/common/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
2019-01-25 17:10:42,504 WARN [main] util.NativeCodeLoader: Unable to load native-hadoop library for your platform... using builtin-java classes where applicable
0 row(s) in 1.6460 seconds
Third.在原集群上复刻新表
hbase(main):003:0> major_compact 'newt1snap'
0 row(s) in 0.0620 seconds
Forth.在目标集群上数据迁移
拷贝新表至目标集群
注意CDH要用hbase用户运行这条命令!这样,迁移过来的表属主为hbase。
这条命令必须在迁移destnation cluster上运行!
distcp之前必须将datasource hbase集群的hosts添加至目标集群的/etc/hosts,否则会报:UnknownHostException: .local的错误。
$ hadoop distcp -i hftp://192.168.40.181:50070/data/hbase/tmp/hbase/data/default/t1 hdfs://192.168.40.116:8020/hbase/data/default/t1
...
...
File System Counters
FILE: Number of bytes read=1981379
FILE: Number of bytes written=2339366
FILE: Number of read operations=0
FILE: Number of large read operations=0
FILE: Number of write operations=0
HDFS: Number of bytes read=0
HDFS: Number of bytes written=1876
HDFS: Number of read operations=25
HDFS: Number of large read operations=0
HDFS: Number of write operations=14
HFTP: Number of bytes read=0
HFTP: Number of bytes written=0
HFTP: Number of read operations=0
HFTP: Number of large read operations=0
HFTP: Number of write operations=0
Map-Reduce Framework
Map input records=10
Map output records=0
Input split bytes=156
Spilled Records=0
Failed Shuffles=0
Merged Map outputs=0
GC time elapsed (ms)=8
Total committed heap usage (bytes)=136839168
File Input Format Counters
Bytes Read=2455
File Output Format Counters
Bytes Written=8
DistCp Counters
Bytes Copied=1876
Bytes Expected=1876
Files Copied=10
Fiveth.在目标集群上表修复
$ hbase hbck -repair
$ hbase hbck -fixAssignments -fixMeta
...
...
19/01/28 17:55:21 INFO util.HBaseFsck: Validating mapping using HDFS state
Summary:
Table hbase:meta is okay.
Number of regions: 1
Deployed on: jiajinyun-7,60020,1548661648608
Table t3 is okay.
Number of regions: 5
Deployed on: jiajinyun-7,60020,1548661648608
Table newt1snap is okay.
Number of regions: 1
Deployed on: jiajinyun-7,60020,1548661648608
Table hbase:namespace is okay.
Number of regions: 1
Deployed on: jiajinyun-7,60020,1548661648608
0 inconsistencies detected.
Status: OK
19/01/28 17:55:21 INFO zookeeper.ZooKeeper: Session: 0x16893671a0a013b closed
19/01/28 17:55:21 INFO zookeeper.ClientCnxn: EventThread shut down
19/01/28 17:55:21 INFO client.ConnectionManager$HConnectionImplementation: Closing master protocol: MasterService
19/01/28 17:55:21 INFO client.ConnectionManager$HConnectionImplementation: Closing zookeeper sessionid=0x16893671a0a013c
19/01/28 17:55:21 INFO zookeeper.ZooKeeper: Session: 0x16893671a0a013c closed
19/01/28 17:55:21 INFO zookeeper.ClientCnxn: EventThread shut down
$ hbase shell
Java HotSpot(TM) 64-Bit Server VM warning: Using incremental CMS is deprecated and will likely be removed in a future release
lis19/01/28 17:55:51 INFO Configuration.deprecation: hadoop.native.lib is deprecated. Instead, use io.native.lib.available
tHBase Shell; enter 'help
Type "exit
Version 1.2.0-cdh5.15.1, rUnknown, Thu Aug 9 09:07:41 PDT 2018
hbase(main):001:0> list
TABLE
newt1snap
t1
t3
3 row(s) in 0.2150 seconds
=> ["newt1snap", "t1", "t3"]
查看表内数据:
hbase(main):002:0> scan 'newt1snap'
ROW COLUMN+CELL
1 column=tab_add:city, timestamp=1548406420347, value=tokyo
1 column=tab_add:name, timestamp=1548406414801, value=ninja
1 row(s) in 0.1350 seconds
迁移成功!
实机生产环境操作记录
下为100G级别生产表迁移实例
源集群操作记录:
# su hadoop
$ hdfs dfs -du -h /hbase/data/default
...
...
以迁移GdRoadStatNew_2018表为例
$ hbase shell
2019-01-31 14:20:58,189 INFO [main] Configuration.deprecation: hadoop.native.lib is deprecated. Instead, use io.native.lib.available
HBase Shell; enter 'help
Type "exit
Version 0.96.1.1-cdh5.0.2, rUnknown, Mon Jun 9 10:45:35 PDT 2014
hbase(main):001:0> list
TABLE
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/share/apps/hbase/hbase-0.96.1.1-cdh5.0.2/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/share/apps/hadoop/hadoop-2.3.0-cdh5.0.2/share/hadoop/common/lib/slf4j-log4j12-1.7.5.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.slf4j.impl.Log4jLoggerFactory]
...
...
test
129 row(s) in 1.7950 seconds
=> ["2015-07-02-id", "2015-11-18-id", "2015-11-18-id_aa", "2015-11-18-time", "2015-11-18-time_aa", "2015-11-19-id", "20170509", "ARRLEA_Q_2015-12-22", "ARRLEA_Q_2016-06-03", "ARRLEA_Q_2017-10-01", "ARRLEA_Q_2017-10-02", "ARRLEA_Q_2017-10-03", "ARRLEA_Q_2017-10-04", "ARRLEA_Q_2017-10-05",
...
...
...
"sz_traf_forecast", "te", "test", "test0104", "test1212", "testwangyi", "zsr_test", "zz_test"]
hbase(main):002:0> snapshot 'GdRoadStatNew_2018', 'snap_GdRoadStatNew_2018'
0 row(s) in 2.2770 seconds
hbase(main):003:0> list_snapshots
SNAPSHOT TABLE + CREATION TIME
snap_GdRoadStatNew_2018 GdRoadStatNew_2018 (Thu Jan 31 14:23:15 +0800 2019)
1 row(s) in 0.2930 seconds
=> ["snap_GdRoadStatNew_2018"]
hbase(main):004:0> clone_snapshot 'snap_GdRoadStatNew_2018', 'new_GdRoadStatNew_2018'
0 row(s) in 2.2400 seconds
下面需要等待compact完成后再执行distcp命令。
hbase(main):005:0> major_compact 'new_GdRoadStatNew_2018'
0 row(s) in 0.8380 seconds
distcp之前必须将datasource hbase集群的hosts添加至目标集群的/etc/hosts,否则会报:UnknownHostException: .local的错误。
目标集群操作记录:
$ hadoop distcp -i hftp://172.16.4.111:50070/hbase/data/default/new_GdRoadStatNew_2018 hdfs://192.168.40.116:8020/hbase/data/default/
19/02/17 15:39:06 INFO tools.OptionsParser: parseChunkSize: blocksperchunk false
19/02/17 15:39:07 INFO tools.DistCp: Input Options: DistCpOptions{atomicCommit=false, syncFolder=false, deleteMissing=false, ignoreFailures=false, overwrite=false, append=false, useDiff=false, useRdiff=false, fromSnapshot=null, toSnapshot=null, skipCRC=false, blocking=true, numListstatusThreads=0, maxMaps=20, mapBandwidth=100, sslConfigurationFile='null', copyStrategy='uniformsize', preserveStatus=[], preserveRawXattrs=false, atomicWorkPath=null, logPath=null, sourceFileListing=null, sourcePaths=[hftp://172.16.4.111:50070/hbase/data/default/new_GdRoadStatNew_2018], targetPath=hdfs://172.16.4.9:8020/hbase/data/default/GdRoadStatNew_2018, targetPathExists=false, filtersFile='null', blocksPerChunk=0, copyBufferSize=8192}
19/02/17 15:39:07 INFO client.RMProxy: Connecting to ResourceManager at compute-5-7/172.16.4.7:8032
19/02/17 15:39:09 INFO tools.SimpleCopyListing: Paths (files+dirs) cnt = 299; dirCnt = 180
19/02/17 15:39:09 INFO tools.SimpleCopyListing: Build file listing completed.
19/02/17 15:39:09 INFO Configuration.deprecation: io.sort.mb is deprecated. Instead, use mapreduce.task.io.sort.mb
19/02/17 15:39:09 INFO Configuration.deprecation: io.sort.factor is deprecated. Instead, use mapreduce.task.io.sort.factor
19/02/17 15:39:09 INFO tools.DistCp: Number of paths in the copy list: 299
19/02/17 15:39:09 INFO tools.DistCp: Number of paths in the copy list: 299
19/02/17 15:39:09 INFO client.RMProxy: Connecting to ResourceManager at compute-5-7/172.16.4.7:8032
19/02/17 15:39:09 INFO mapreduce.JobSubmitter: number of splits:27
19/02/17 15:39:09 INFO mapreduce.JobSubmitter: Submitting tokens for job: job_1550287828159_0022
19/02/17 15:39:10 INFO impl.YarnClientImpl: Submitted application application_1550287828159_0022
19/02/17 15:39:10 INFO mapreduce.Job: The url to track the job: http://compute-5-7:8088/proxy/application_1550287828159_0022/
19/02/17 15:39:10 INFO tools.DistCp: DistCp job-id: job_1550287828159_0022
19/02/17 15:39:10 INFO mapreduce.Job: Running job: job_1550287828159_0022
19/02/17 15:39:16 INFO mapreduce.Job: Job job_1550287828159_0022 running in uber mode : false
19/02/17 15:39:16 INFO mapreduce.Job: map 0% reduce 0%
19/02/17 15:39:33 INFO mapreduce.Job: map 2% reduce 0%
19/02/17 15:39:34 INFO mapreduce.Job: map 16% reduce 0%
19/02/17 15:39:35 INFO mapreduce.Job: map 19% reduce 0%
19/02/17 15:44:12 INFO mapreduce.Job: map 20% reduce 0%
19/02/17 15:45:31 INFO mapreduce.Job: map 21% reduce 0%
19/02/17 15:45:38 INFO mapreduce.Job: map 22% reduce 0%
19/02/17 15:46:39 INFO mapreduce.Job: map 23% reduce 0%
19/02/17 15:46:40 INFO mapreduce.Job: map 25% reduce 0%
19/02/17 15:49:11 INFO mapreduce.Job: map 27% reduce 0%
19/02/17 15:49:29 INFO mapreduce.Job: map 30% reduce 0%
19/02/17 15:50:00 INFO mapreduce.Job: map 31% reduce 0%
19/02/17 15:50:24 INFO mapreduce.Job: map 33% reduce 0%
19/02/17 15:51:12 INFO mapreduce.Job: map 35% reduce 0%
19/02/17 15:52:19 INFO mapreduce.Job: map 37% reduce 0%
19/02/17 15:52:31 INFO mapreduce.Job: map 40% reduce 0%
19/02/17 15:52:49 INFO mapreduce.Job: map 42% reduce 0%
19/02/17 15:56:39 INFO mapreduce.Job: map 44% reduce 0%
19/02/17 15:56:41 INFO mapreduce.Job: map 46% reduce 0%
19/02/17 15:58:11 INFO mapreduce.Job: map 48% reduce 0%
19/02/17 16:00:01 INFO mapreduce.Job: map 51% reduce 0%
19/02/17 16:00:23 INFO mapreduce.Job: map 54% reduce 0%
19/02/17 16:00:44 INFO mapreduce.Job: map 57% reduce 0%
19/02/17 16:00:56 INFO mapreduce.Job: map 58% reduce 0%
19/02/17 16:01:35 INFO mapreduce.Job: map 59% reduce 0%
19/02/17 16:03:14 INFO mapreduce.Job: map 63% reduce 0%
19/02/17 16:03:17 INFO mapreduce.Job: map 65% reduce 0%
19/02/17 16:03:41 INFO mapreduce.Job: map 67% reduce 0%
19/02/17 16:03:43 INFO mapreduce.Job: map 70% reduce 0%
19/02/17 16:03:55 INFO mapreduce.Job: map 71% reduce 0%
19/02/17 16:04:08 INFO mapreduce.Job: map 72% reduce 0%
19/02/17 16:04:24 INFO mapreduce.Job: map 73% reduce 0%
19/02/17 16:05:01 INFO mapreduce.Job: map 74% reduce 0%
19/02/17 16:05:29 INFO mapreduce.Job: map 77% reduce 0%
19/02/17 16:06:15 INFO mapreduce.Job: map 84% reduce 0%
19/02/17 16:06:21 INFO mapreduce.Job: map 85% reduce 0%
19/02/17 16:06:36 INFO mapreduce.Job: map 88% reduce 0%
19/02/17 16:06:56 INFO mapreduce.Job: map 89% reduce 0%
19/02/17 16:07:14 INFO mapreduce.Job: map 90% reduce 0%
19/02/17 16:07:27 INFO mapreduce.Job: map 91% reduce 0%
19/02/17 16:07:54 INFO mapreduce.Job: map 92% reduce 0%
19/02/17 16:09:01 INFO mapreduce.Job: map 94% reduce 0%
19/02/17 16:09:21 INFO mapreduce.Job: map 96% reduce 0%
19/02/17 16:09:22 INFO mapreduce.Job: map 98% reduce 0%
19/02/17 16:10:05 INFO mapreduce.Job: map 99% reduce 0%
19/02/17 16:10:28 INFO mapreduce.Job: map 100% reduce 0%
19/02/17 16:10:30 INFO mapreduce.Job: Job job_1550287828159_0022 completed successfully
19/02/17 16:10:30 INFO mapreduce.Job: Counters: 38
File System Counters
FILE: Number of bytes read=0
FILE: Number of bytes written=4118003
FILE: Number of read operations=0
FILE: Number of large read operations=0
FILE: Number of write operations=0
HDFS: Number of bytes read=93105
HDFS: Number of bytes written=124610412636
HDFS: Number of read operations=988
HDFS: Number of large read operations=0
HDFS: Number of write operations=506
HFTP: Number of bytes read=0
HFTP: Number of bytes written=0
HFTP: Number of read operations=0
HFTP: Number of large read operations=0
HFTP: Number of write operations=0
Job Counters
Launched map tasks=27
Other local map tasks=27
Total time spent by all maps in occupied slots (ms)=40877675
Total time spent by all reduces in occupied slots (ms)=0
Total time spent by all map tasks (ms)=40877675
Total vcore-milliseconds taken by all map tasks=40877675
Total megabyte-milliseconds taken by all map tasks=41858739200
Map-Reduce Framework
Map input records=299
Map output records=0
Input split bytes=3105
Spilled Records=0
Failed Shuffles=0
Merged Map outputs=0
GC time elapsed (ms)=15744
CPU time spent (ms)=1844160
Physical memory (bytes) snapshot=6710362112
Virtual memory (bytes) snapshot=78289428480
Total committed heap usage (bytes)=7559708672
File Input Format Counters
Bytes Read=90000
File Output Format Counters
Bytes Written=0
DistCp Counters
Bytes Copied=124610412636
Bytes Expected=124610412636
Files Copied=299
$ hbase hbck -repair
...
...
19/01/31 16:37:55 INFO util.HBaseFsck: Finishing hbck
Summary:
Table new_GdRoadStatNew_2018 is okay.
Number of regions: 59
Deployed on: jiajinyun-7,60020,1548905090315
Table hbase:meta is okay.
Number of regions: 1
Deployed on: jiajinyun-7,60020,1548905090315
Table hbase:namespace is okay.
Number of regions: 1
Deployed on: jiajinyun-7,60020,1548905090315
0 inconsistencies detected.
Status: OK
19/01/31 16:37:55 INFO zookeeper.ZooKeeper: Session: 0x168a1b2b1900492 closed
19/01/31 16:37:55 INFO zookeeper.ClientCnxn: EventThread shut down
19/01/31 16:37:55 INFO client.ConnectionManager$HConnectionImplementation: Closing master protocol: MasterService
19/01/31 16:37:55 INFO client.ConnectionManager$HConnectionImplementation: Closing zookeeper sessionid=0x168a1b2b1900493
19/01/31 16:37:55 INFO zookeeper.ZooKeeper: Session: 0x168a1b2b1900493 closed
19/01/31 16:37:55 INFO zookeeper.ClientCnxn: EventThread shut down
改表名,搞定!