也做过集群迁移,一年内迁移了两次,整体流程和下面大致相同, 但操作也有些不同。采用直接从源集群A distcp到目标集群B,任务在A集群中启动,省去集群C,也不用做什么集群的配置文件制定。但是一般都会跨网段,比如XX云-> YY云,就需要外网的带宽要足够,一般架设的VPN只能达到200MB/s。
Hbase集群迁移
- 源集群A
- 目标集群B
- 启动迁移任务的集群C,如果A或B集群的磁盘够大,也可以选择其中任意一个集群,用来启动迁移任务。
- 数据流向:A->C->B
分别消耗A集群的出口流量,C集群的出入流量,B集群的入口流量。由于pipeline的写入模式,流量还会在B集群内部再放大。
一、准备源集群A和目标集群B
- 由于网络的特殊性,需要在源集群A准备配置文件~/hadoop/etc/hadoop/iptable,内容如下
10.xxx.xxx.xxx 11.xxx.xxx.xxx
xxx用真实的IP地址替换,每个IP地址一行,集群有多少台机器,就有多少行,表示将10的IP转换为11的IP。
- 搭建目标集群B
二、在执行迁移任务的集群C开启yarn
distcp如果使用分布式模式,依赖于yarn,需要在C集群配置和启动yarn。
- 从下载hadoop-2.7版配置到yarn集群的各个节点(主要是yarn-site.xml, yarn-env.sh, mapred-site.xml三个文件),并把yarn-site.xml中的rm.host替换为ResourceManager地址
- 在hmaster节点启动ResourceManager
#yarn-daemon.sh start resourcemanager
- 在regionserver节点启动NodeManager
#sbin/yarn-daemons.sh --hosts <yarn机器列表> start nodemanager
三、通知业务执行双写
四、在集群C上准备配置文件distcp.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!-- Put site-specific property overrides in this file. -->
<configuration>
<property>
<name>dfs.nameservices</name>
<value>$hdfscluster-A,$hdfscluster-B,$hdfscluster-C</value>
</property>
<property>
<name>dfs.ha.namenodes.$hdfscluster-A</name>
<value>nn1,nn2</value>
</property>
<property>
<name>dfs.namenode.rpc-address.$hdfscluster-A.nn1</name>
<valu>$Ann1ip:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.$hdfscluster-A.nn2</name>
<value>$Ann2ip:8020</value>
</property>
<property>
<name>dfs.ha.namenodes.$hdfscluster-B</name>
<value>nn1,nn2</value>
</property>
<property>
<name>dfs.namenode.rpc-address.$hdfscluster-B.nn1</name>
<value>$Bnn1ip:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.$hdfscluster-B.nn2</name>
<value>$Bnn2ip:8020</value>
</property>
<property>
<name>dfs.ha.namenodes.$hdfscluster-C</name>
<value>nn1,nn2</value>
</property>
<property>
<name>dfs.namenode.rpc-address.$hdfscluster-C.nn1</name>
<value>$Cnn1ip:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.$hdfscluster-C.nn2</name>
<value>$Cnn2ip:8020</value>
</property>
<property>
<name>dfs.client.failover.proxy.provider.$hdfscluster-A</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<property>
<name>dfs.client.failover.proxy.provider.$hdfscluster-B</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<property>
<name>dfs.client.failover.proxy.provider.$hdfscluster-C</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<property>
<name>fs.trash.interval</name>
<value>10080</value>
</property>
</configuration>
五、在源集群A上关闭和恢复compaction和split
- 进入regionserver的web页面,进入conf,拿到regionserver当前的3个配置的值:
hbase.store.stripe.compaction.minFilesL0,默认值是4
hbase.store.stripe.compaction.minFiles,默认值是3
hbase.hstore.compaction.min,默认值是3
记录这些值,用于迁移完成后的恢复.如果没有找到,就用上面给的默认值
- 在hbase shell中给表设置属性,来禁用compaction。 将$table替换成实际的表名; 将split policy设置为DisabledRegionSplitPolicy来禁用表级别的split。 为所有表执行以下步骤:
alter '$table', CONFIGURATION => {'hbase.hstore.compaction.min' => '9999', 'hbase.store.stripe.compaction.minFilesL0' => '9999', 'hbase.store.stripe.compaction.minFiles' => '9999'},METADATA => {'SPLIT_POLICY' => 'org.apache.hadoop.hbase.regionserver.DisabledRegionSplitPolicy'}
六、检查是否还有正在跑的compaction、split
在所有机器上执行jstack,搜索compaction和split,如果都是waitting状态,可以认为都ok了。
七、集群复制distcp
- 1. 在目标集群B上创建同步路径
#hadoop dfs -mkdir /idc_move
- 2. 在集群C执行复制命令distcp
#nohup hadoop distcp -conf ./distcp.xml -m 50 -bandwidth 2 -p hdfs://$hdfscluster-A/hbase/data/default/$tablename hdfs://$hdfscluster-B/idc_move/$tablename 2>&1 > distcp.log
- 3. 到yarn页面检查作业进度
http://$resourcemanagerhost:8088/cluster/apps
本地模式
如果数据量不大,可以用本地模式拷贝单线程拷贝数据,命令如下:
hadoop distcp -conf <address.xml> -bandwidth <bandwith_mb> -p <src> <dest>
分布式模式
分布式模式依赖于yarn,需要在第二步启动迁移任务的集群C配置和启动yarn。
#hadoop distcp -conf <address.xml> -m <max_concurrent> -bandwidth <bandwith_mb> -p <src> <dest>
参数解释:
- address.xml 存放有源集群与目标集群nn信息的配置文件
- max_concurrent 最大拷贝并发数
- bandwith_mb 线程拷贝带宽限制,单位MB/s。bandwith_mb * max_concurrent就是整个集群的拷贝带宽,如果是本地模式,只能单线程拷贝,-m参数无效,这个参数就是全局的拷贝数据
- src 源数据地址 hdfs://src-hdfs-name/src-path
- dest 目标数据地址 hdfs://src-hdfs-name/dest-path
- -p选项 保留源文件的block大小、存储类型信息(ONE_SSD、ALL_SSD、etc..)
八、在源集群A恢复compaction和split
- distcp完成后,恢复compaction和split,进入hbase shell,为所有表执行:
alter '$table', CONFIGURATION => {'hbase.hstore.compaction.min' => 'x', 'hbase.store.stripe.compaction.minFilesL0' => 'y', 'hbase.store.stripe.compaction.minFiles' => 'z'},METADATA => {'SPLIT_POLICY' => 'org.apache.hadoop.hbase.regionserver.IncreasingToUpperBoundRegionSplitPolicy'}
其中,x、y、z是这3个参数的原始值,在步骤1中得到的。
九、在目标集群B Move所有列簇
在复制好数据的目标集群B,将hdfs的路径/$TO_LOAD_PATH/$table/region/cf*/data改成/$TO_LOAD_PATH/to_load_$table/cf*/data
#hadoop fs -mkdir -p $TO_LOAD_PATH/toload_$move_table_name/$split_table_cf
#hadoop fs -mv $TO_LOAD_PATH/$move_table_name/*/$split_table_cf/* $TO_LOAD_PATH/toload_$move_table_name/$split_table_cf/
十、在目标集群B Load数据到Hbase
- 1. 如果Bulkload时一个Region包含的Hfile数超过32个,需要调整配置文件/home/hadoop/hbase-current/conf/hbase-site.xml
<property>
<name>hbase.mapreduce.bulkload.max.hfiles.perRegion.perFamily</name>
<value>999999</value>
</property>
- 2. Load数据到Hbase
#hbase org.apache.hadoop.hbase.mapreduce.LoadIncrementalHFiles hdfs://$hbaserootdir/$TO_LOAD_PATH/toload_$table $table
- 3. 将内存数据写磁盘
hbase>flush $table
- 4. 将Hlog重新排序
hbase>disable $table
hbase>enable $table
- 5. 将region均分在所有regionserver,并清除重复数据
hbase>major_compact '$table'
十一、检查hbasemaster上各表的大小是否于原集群同等上下
- 在浏览器中输入http://$hbasemaster:$port/master-status,查找“TableSize”,看看源集群和目标集群的值是否相近。
- 如果值相差很大,看看是不是一边开启数据压缩,一边没开启。COMPRESSION => 'LZO'