主备双活实例开发指南

最近更新时间:2025-12-09 18:01:01

我的收藏

操作场景

使用 Java 通过高可用客户端( hbase-ha-client )访问 EMR Serverless HBase 主备双活实例并进行建表和查询等操作。

准备工作

1. 已经创建了一个 EMR Serverless HBase 主备双活实例且实例状态均为运行中。
2. 已经创建一台与 EMR Serverless HBase 主备双活实例同 VPC 和子网的 CVM 实例(后面简称 CVM 客户机)。
3. 在 CVM 客户机上已安装 Java 环境并配置环境变量,安装要求 JDK1.8 以上版本,如未安装,https://tencent.github.io/konajdk/ 。
4. 已在 EMR Serverless HBase 主备双活实例信息页获取 Serverless HBase 主备实例的 ZooKeeper 地址。
说明:
更多 HBase API 使用请查阅 Apache HBase 官网

操作步骤

Settings.xml配置

确保开发环境下有合适的 JDK 版本,安装配置 Maven 的环境变量,如果您使用 IDE,请在 IDE 中设置 Maven 相关配置。如有需要,使用腾讯云镜像源加速Maven,在 Maven 配置文件 settings.xml 添加如下 repository mirror 和 profile。
<mirror>
<id>nexus-tencentyun</id>
<mirrorOf>*</mirrorOf>
<name>Nexus tencentyun</name>
<url>http://mirrors.cloud.tencent.com/nexus/repository/maven-public/</url>
</mirror>
<profiles>
<profile>
<id>Repository Proxy</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<repositories>
<repository>
<id>tencentemr-hbase-ha-client-releases</id>
<name>releases</name>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
</repositories>
</profile>
</profiles>

新建一个Maven 工程

在命令行下进入您想要新建工程的目录,输入如下命令新建一个 Maven 工程。
mvn archetype:generate -DgroupId=com.tencent.cloud -DartifactId=test-serverless-hbase -Dversion=1.0 -DarchetypeArtifactId=maven-archetype-quickstart
创建成功后,在工程目录下就会生成一个名为 test-serverless-hbase 的工程文件夹。其中的文件结构如下所示。pom.xml 文件主要用于依赖管理和打包配置,Java 文件夹下放置您的源代码。
test-hbase
├── pom.xml
└── src
├── main
│ └── java
│ └── com
│ └── tencent
│ └── cloud
│ └── App.java
└── test
└── java
└── com
└── tencent
└── cloud
└── AppTest.java

添加配置和样例代码

在 pom.xml 文件中添加 Maven 依赖、打包和编译插件。
<dependencies>
<!-- https://mvnrepository.com/artifact/org.apache.hbase/hbase-client -->
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>2.4.5</version>
</dependency>
<dependency>
<groupId>com.tencentcloud.emr</groupId>
<artifactId>hbase-ha-client</artifactId>
<version>1.0.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/log4j/log4j -->
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.10.1</version>
<configuration>
<source>8</source>
<target>8</target>
<encoding>utf-8</encoding>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
<archive>
<manifest>
<!-- 此处指定main方法入口的class -->
<mainClass>com.tencent.cloud.App</mainClass>
</manifest>
</archive>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>

【可选】如果在之后的调试中遇到样例执行失败需要从标准输出中获取日志定位错误,或者您希望保存操作日志到指定目录 target/serverless-hbase.log,您可以在 main 文件夹下创建 Java 配置文件目录 resources,创建 log4j.properties 文件并在 log4j.properties 文件中添加 log4j 日志信息打印模块的配置信息。
log4j.rootLogger=INFO, stdout, logfile
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m%n
log4j.appender.logfile=org.apache.log4j.FileAppender
log4j.appender.logfile.File=target/serverless-hbase.log
log4j.appender.logfile.layout=org.apache.log4j.PatternLayout
log4j.appender.logfile.layout.ConversionPattern=%d %p [%c] - %m%n
App.java 样例代码如下:
package com.tencent.cloud;

import com.tencentcloud.emr.HAConnection;
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.util.Bytes;

import java.io.IOException;

import static org.apache.hadoop.hbase.HConstants.REPLICATION_SCOPE_GLOBAL;

/**
* 通过 Java API 访问 Serverless HBase 主备双活实例
*/
public class App {
public static void main(String[] args) throws IOException {
// $quorum和$standbyQuorum分别为主备实例的Zookeeper地址,在控制台实例信息页面通过访问方式模块的zookeeper地址获取。
// 示例:conf.set("hbase.zookeeper.quorum", "10.0.0.8,10.0.0.11,10.0.0.5");
// 示例:conf.set("hbase.zookeeper.quorum.standby", "10.0.0.21,10.0.0.22,10.0.0.24");
Configuration conf = HBaseConfiguration.create();
conf.set("hbase.zookeeper.quorum", "$quorum");
conf.set("hbase.zookeeper.quorum.standby", "$standbyQuorum");

// hbase.client.pause为客户端重试间隔,单位为毫秒,默认为100毫秒。
// hbase.client.retries.number为客户端重试次数,默认为15次。
// 对同一实例请求重试耗尽后,会自动切换到备实例进行重试,两个实例均耗尽重试后,会返回错误。
conf.setInt("hbase.client.pause", 10);
conf.setInt("hbase.client.retries.number", 5);

HAConnection connection;
connection = new HAConnection(conf);

Admin admin = connection.getAdmin();

String TABLE_NAME = "test1";
String COLUMN_FAMILY = "cf";

TableDescriptorBuilder tableDescriptorBuilder = TableDescriptorBuilder.newBuilder(TableName.valueOf(TABLE_NAME));
// 设置全局复制
tableDescriptorBuilder.setColumnFamily(ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(COLUMN_FAMILY)).setScope(REPLICATION_SCOPE_GLOBAL).build());
TableDescriptor tableDescriptor = tableDescriptorBuilder.build();

System.out.println("Creating table. ");
if (admin.tableExists(tableDescriptor.getTableName())) {
admin.disableTable(tableDescriptor.getTableName());
admin.deleteTable(tableDescriptor.getTableName());
}
admin.createTable(tableDescriptor);

System.out.println("Put data. ");
Table table1 = connection.getTable(TableName.valueOf(TABLE_NAME));
Put put1 = new Put(Bytes.toBytes("row1"));
put1.addColumn(Bytes.toBytes(COLUMN_FAMILY), Bytes.toBytes("a"),
Bytes.toBytes("value1"));
table1.put(put1);
Put put2 = new Put(Bytes.toBytes("row2"));
put2.addColumn(Bytes.toBytes(COLUMN_FAMILY), Bytes.toBytes("b"),
Bytes.toBytes("value2"));
table1.put(put2);
Put put3 = new Put(Bytes.toBytes("row3"));
put3.addColumn(Bytes.toBytes(COLUMN_FAMILY), Bytes.toBytes("c"),
Bytes.toBytes("value3"));
table1.put(put3);

System.out.println("Get data. ");
Get get1 = new Get(Bytes.toBytes("row1"));
Result row = table1.get(get1);
if (row.isEmpty()) {
System.out.println("未找到行数据");
return;
}
System.out.println("行键: " + Bytes.toString(row.getRow()));
byte[] value = row.getValue(Bytes.toBytes(COLUMN_FAMILY), Bytes.toBytes("a"));
if (value != null) {
System.out.println("值: " + Bytes.toString(value));
}

connection.close();

System.out.println(" Done.");
}
}

编译代码并打包上传

使用本地命令行进入工程目录,执行以下指令对工程进行编译打包。
mvn package
日志打印 build success 表示操作成功,在工程目录下的 target 文件夹中能够看到打包好的 jar 包,您需要将以 with-dependencies 为尾缀的 jar 包通过 CVM 实例控制台中的上传文件功能上传到 CVM 客户机中。
若 CVM 客户机可以通过公网 IP 访问,也可以在本地命令行模式下运行以下命令上传文件。
scp $localfile root@公网IP地址:$remotefolder
其中,$localfile 是您的本地文件的路径加名称,root 为 CVM 服务器用户名,公网 IP 可以在 CVM 客户机控制台查看。$remotefolder 是您想存放文件的 CVM 服务器路径。上传完成后,在 CVM 客户机命令行中即可查看对应文件夹下是否有相应文件。

执行样例并查看结果

登录 CVM 客户机,切换到对应文件夹下,使用如下命令执行样例。
java -jar $package.jar
运行代码,在控制台输出“Done”后,说明所有的操作已完成。您可以切换到 HBase shell 中通过 list 命令来查看使用 API 创建的 HBase 表是否在主备实例均创建成功,若成功可通过 scan 命令来查看表的具体内容。
hbase:001:0> list 'test1'
TABLE
test1
1 row(s)
Took 0.4315 seconds
=> ["test1"]
hbase:002:0> scan 'test1'
ROW COLUMN+CELL
row1 column=cf:a, timestamp=2024-07-16T16:20:38.685, value=value1
row2 column=cf:b, timestamp=2024-07-16T16:20:38.690, value=value2
row3 column=cf:c, timestamp=2024-07-16T16:20:38.695, value=value3
3 row(s)
Took 0.1231 seconds
hbase:003:0> exit