Hbase 迁移小结:从实践中总结出的最佳迁移策略

在数据存储和处理领域,HBase作为一种分布式、可扩展的NoSQL数据库,被广泛应用于大规模数据的存储和分析。然而,随着业务需求的变化和技术发展的进步,有时候我们需要将现有的HBase数据迁移到其他环境或存储系统。HBase数据迁移是一个复杂而关键的任务,它涉及到保证数据完整性、准确性和安全性,同时还需要考虑版本兼容性、网络带宽、数据量等因素。从Hbase 本身的设计架构上可以知道 hbase的表是基于 hadoop HDFS 构建,所以一般在迁移Hbase 表数据的时候需要关注到两个维度,hbase层和hdfs层,下图包含常见的一些迁移工具和手段。 

Hbase 迁移小结:从实践中总结出的最佳迁移策略_第1张图片

在不同的适用场景下,对于hbase 的迁移是需要采用不同的方式的,下面推荐使用基于 Snapshot 迁移和利用hive外表关联hbase迁移;

1.基于 Snapshot 迁移具体实施步骤

第一步:需要在源集群中执行创建表的快照

snapshot 'poi_geohash','snapshot_poi_geohash'

此时生成的快照是存储在hdfs上的,下面一步需要hbase 的快照同步工具,将表的快照同步到新的hbase集群中;

第二步:同步快照文件 

hbase org.apache.hadoop.hbase.snapshot.ExportSnapshot -snapshot snapshot_poi_geohash -copy-from hdfs://${old_namenoe_ip}:8020/hbase -copy-to hdfs://${new_namenoe_ip}:8020/hbase -mappers 30 -bandwidth 8192

参数说明:

  • -org.apache.hadoop.hbase.snapshot.ExportSnapshot:HBase 提供的快照导出工具类。
  • -snapshot snapshot_poi_geohash:指定要导出的快照名称。
  • -copy-from hdfs://${old_namenoe_ip}:8020/hbase:指定要从哪个 HDFS 路径下的文件进行导出,${old_namenode_ip} 是旧的 NameNode IP 地址。
  • -copy-to hdfs://${new_namenoe_ip}:8020/hbase:指定导出的文件将被存储到哪个 HDFS 路径下,${new_namenode_ip} 是新的 NameNode IP 地址。
  • -mappers 30:指定并发执行的 Mapper 数量,即同时处理的任务数。这里设置为 30。
  • -bandwidth 8192:指定数据传输的带宽限制,单位为 KB/s。这里设置为 8192,即 8 MB/s。 

任务启动的截图:

Hbase 迁移小结:从实践中总结出的最佳迁移策略_第2张图片

任务结束的截图:

Hbase 迁移小结:从实践中总结出的最佳迁移策略_第3张图片

说明:在使用这个工具的使用,操作的客户端必须是Yarn集群的客户端节点,否则上面的程序默认使用本地的资源,如果数据量很大,将会同步的很慢。

注意点1:提交的任务终端,不能手动kill,否则任务虽然正常执行,但是最终的数据会同步失败。(执行上面命令时,建议配合nohup,放在后台执行)

注意点2:这里还有一个细节点需要注意,就是用来同步的用户,如果是CDH版本的,就推荐使用hbase用户,如果是其他非hbase用户,在下面第三步中恢复数据的时候就会有权限上的报错。

例如下面截图的报错,当时同步的时候是用的hdfs用户,在第三步恢复表数据的时候就会有下面的(权限报错);

Hbase 迁移小结:从实践中总结出的最佳迁移策略_第4张图片

如果误操作出现上面的情况,我们在执行第三步的时候,命令的状态是会一直卡着的,此时在hbase 的master web 页面上可以看到此时表是在一直上锁的。

图片

Hbase 迁移小结:从实践中总结出的最佳迁移策略_第5张图片

Hbase 迁移小结:从实践中总结出的最佳迁移策略_第6张图片

处理方式:此时因为是权限问题导致的,所以处理的方式也就很简单,只需要参考master的报错信息(上面有截图),添加对应的目录权限即可。

添加权限:

$ hdfs dfs -chown -R hbase:hbase /hbase/ 

这中间不要做其他操作,权限更改完成之后,重启master节点即可恢复正常。

Hbase 迁移小结:从实践中总结出的最佳迁移策略_第7张图片

第三步:快照恢复表结构以及数据

hbase(main):001:0> clone_snapshot 'snapshot_poi_geohash','poi_geohash'

说明:这里我们测试表的namespace是默认的default,如果原表是在自定义的namespace下,此时在目标数据库还需要手动创建namespace。

参考命令:

$ hbase shell
hbase(main):013:0> create_namespace 'namespace_name'

2.利用hive外表关联hbase迁移

这个是基于hive可以通过外部表(External Table)的方式来访问HBase中的数据。这种在实施的过程操作上相对比较简便。

下面给大家演示一个案例;

在目标hbase中已存在hbase表:poi_geohash

图片

1.首先进入到hive的客户端,创建hive的外部表,关联到hbase表。

# 建立hbase外表需要指定对应的zk
set hbase.zookeeper.quorum=10.6.24.xxx:2181,10.6.24.xxx:2181,10.6.24.xxx:2181;  ## 指定hbase 的zk信息

CREATE EXTERNAL TABLE poi_geohash_hive1
(
rowkey string,
lat_lon_list string,
name_list string,
type_id_list string,
type_list string
)STORED BY "org.apache.hadoop.hive.hbase.HBaseStorageHandler" WITH
SERDEPROPERTIES ("hbase.columns.mapping"=":key,cf:lat_lon_list,cf:name_list,cf:type_id_list,cf:type_list") TBLPROPERTIES ("hbase.table.name" = "poi_geohash");

2.查询hive表,看是否有数据来验证关联成功

select * from poi_geohash_hive;

3.将poi_geohash_hive表的数据导入到另一张hive内部表中。

CREATE TABLE poi_geohash_hive_new AS
SELECT
  rowkey,
  lat_lon_list,
  name_list,
  type_id_list,
  type_list
FROM
  poi_geohash_hive1;

4.在新的hbase中创建新的表,表特性和源hbase表一致。

代码略

5.重复1的操作,进入到hive的客户端,创建hive的外部表,关联到hbase表。

# 建立hbase外表需要指定对应的zk
set hbase.zookeeper.quorum=${new_zk_ip};  ## 此时需要set 新的hbase集群的zk的信息

CREATE EXTERNAL TABLE poi_geohash_hive2
(
rowkey string,
lat_lon_list string,
name_list string,
type_id_list string,
type_list string
)STORED BY "org.apache.hadoop.hive.hbase.HBaseStorageHandler" WITH
SERDEPROPERTIES ("hbase.columns.mapping"=":key,cf:lat_lon_list,cf:name_list,cf:type_id_list,cf:type_list") TBLPROPERTIES ("hbase.table.name" = "poi_geohash");

注意:这个时候通过hive关联的是需要迁移的,2.4步骤中新创建的hbase表;

任务结束,验证新hbase表中有数据且数据完整,及完成对hbase表数据的迁移;

小tips:通常在严重hbase表数据的完整性的时候,简单点的方式就是统计rowkey的数量。

常规的统计方式有 :

1.使用hbase-shell 自带count命令

2.使用hbase.RowCounter工具跑MR任务

3.使用HBase协处理器Coprocessor

但是性能上第三种(Coprocessor)是最快的,下面简单介绍下HBase协处理器统计表的一个小案例;


package com.ds;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.TableName;
import org.apache.hadoop.hbase.client.*;
import org.apache.hadoop.hbase.client.coprocessor.AggregationClient;
import org.apache.hadoop.hbase.client.coprocessor.LongColumnInterpreter;

public class CoprocessorExampleHbase2 {

    public static void main(String[] args) {
        try {
            long start_t = System.currentTimeMillis();
            String zkQuorum = null;
            String tableName = null;
            for (int i = 0; i < args.length; i++) {
                if (args[i].equals("-zk")) {
                    zkQuorum = args[i + 1];
                } else if (args[i].equals("-tb")) {
                    tableName = args[i + 1];
                }
            }

            if (zkQuorum == null || tableName == null) {
                System.out.println("请指定正确的参数: -zk [Zookeeper Quorum] -tb [Table Name]");
                return;
            }

            // 初始化HBase配置
            Configuration customConf = new Configuration();
            customConf.set("hbase.rootdir", "hdfs:///hbase");
            customConf.set("hbase.zookeeper.property.clientPort", "2181");
            customConf.setStrings("hbase.zookeeper.quorum", zkQuorum.split(","));
            customConf.setLong("hbase.rpc.timeout", 600000);
            customConf.setLong("hbase.client.scanner.caching", 1000);
            customConf.set("zookeeper.session.timeout", "180000");
            Configuration configuration = HBaseConfiguration.create(customConf);
            AggregationClient aggregationClient = new AggregationClient(configuration);
            Scan scan = new Scan();
            long rowCount = aggregationClient.rowCount(TableName.valueOf(tableName), new LongColumnInterpreter(), scan);
            System.out.println("******************统计结果***********************");
            System.out.println("统计总耗时:" + (System.currentTimeMillis() - start_t) + "毫秒");
            System.out.println("表【" + tableName + "】统计总数:" + rowCount);
        } catch (Exception e) {
            e.printStackTrace();
        } catch (Throwable e) {
            e.printStackTrace();
        }
    }
}

在hbase配置 hbase-site.xm  中添加如下配置,并重启hbase;



   hbase.coprocessor.user.region.classes
   org.apache.hadoop.hbase.coprocessor.AggregateImplementation
 

使用方式,直接在hbase 的客户端节点执行:

hadoop jar hbase2-1.0-SNAPSHOT-jar-with-dependencies.jar com.ds.CoprocessorExampleHbase2 -zk zk地址 -tb hbase表名

最终的输出结果:

Hbase 迁移小结:从实践中总结出的最佳迁移策略

你可能感兴趣的:(hbase,数据库,大数据)