一 前期准备篇
在java端创建一个Maven项目 ,将Hbase的jar包和依赖等添加到 pom.xml 文件中,添加内容如下 ;
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.8</maven.compiler.source>
<maven.compiler.target>1.8</maven.compiler.target>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.zookeeper</groupId>
<artifactId>zookeeper</artifactId>
<version>3.4.6</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-auth</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-client</artifactId>
<version>2.2.5</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-client</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.hadoop</groupId>
<artifactId>hadoop-common</artifactId>
<version>3.2.1</version>
</dependency>
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-server</artifactId>
<version>2.2.5</version>
</dependency>
<!-- 使用mr程序操作hbase 数据的导入 -->
<dependency>
<groupId>org.apache.hbase</groupId>
<artifactId>hbase-mapreduce</artifactId>
<version>2.2.5</version>
</dependency>
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>
<!-- phoenix 凤凰 用来整合Hbase的工具 -->
<dependency>
<groupId>org.apache.phoenix</groupId>
<artifactId>phoenix-core</artifactId>
<version>5.0.0-HBase-2.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-assembly-plugin</artifactId>
<version>2.6</version>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id>
<!-- bind to the packaging phase -->
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
可能遇到的异常及解决办法 : 导入/下载jar包依赖的时候可能会出现个别不能下载成功的jar包 ,根据提示,将没有成功的jar文件删除掉,重新在 pom.xml 文件中单击右键,选择"maven"=>"reload project" ,和单击界面右上角"maven栏"=>单击左上角的刷新符号 ,然后回到pom.xml文件界面重新下载之前没有下载成功的文件 .
二 实践篇
1 Hbase的java客户端入门程序
/**
* description : 使用java客户端操作 hbase
* 1)zookeeper上记录着hbase集群的信息
* 2)获取hbase的连接对象
* 3)建表 建namespace 修改表结构.. 对数据的操作.. get put delete
* 4) admin 管理者 建namespace 建表 表结构 删除表/名称空间 工具 合并切割移动 刷写
* 5) table 表对象 对数据操作 put delete get scan
**/
public class Test {
public static void main(String[] args) throws IOException {
// 获取 zookeeper 的连接对象
// 1 创建配置对象
Configuration conf = HBaseConfiguration.create();
// 1.1 设置 zookeeper的位置 找到hbase
conf.set("hbase.zookeeper.quorum","doit03:2181,doit04:2181,doit05:2181");
// 2 获取连接对象
Connection connection = ConnectionFactory.createConnection(conf);
// 3 获取操作对象
Admin admin = connection.getAdmin();
// 3.1 操作hbase 得到默认namespace的名字和其下的表的名字
TableName[] tableNames = admin.listTableNames();
// 遍历,将所有tablename取出来
for (TableName tableName : tableNames) {
// 获取表的名字
String tbname = tableName.getNameAsString();
// 获取 名字空间
String namespace = tableName.getNamespaceAsString();
System.out.println(namespace+"---"+tbname);
}
// 关闭连接
admin.close();
connection.close();
}
}
2 为了减少重复编写代码 ,将"获取配置对象 / 设置 zookeeper 位置 / 获取连接对象"的流程封装成方法 ,每次需要用到的时候直接调用就可以了
/**
*
* @Description : 将 获取配置对象 /设置zookeeper位置 /获取连接对象 步骤封装起来
*
**/
public class HabaseUtil {
public static Connection getHbaseConnection() throws IOException {
// 获取 hbase 配置对象
Configuration conf = HBaseConfiguration.create();
// 设置 zookeeper 位置
conf.set("hbase.zookeeper.quorum","linux03:2181,linux04:2181,linux05:2181");
//创建连接对象
Connection con = ConnectionFactory.createConnection(conf);
return con;
}
}
3 操作 namespace( 创建 / 删除 / 设置属性 / 更新属性)
/**
*
* @Description : 操作名字空间
**/
public class NewSpaceClient {
public static void main(String[] args) throws IOException {
// 调用创建名字空间的方法
createNameSpace();
............................................................
// 获取hbase连接对象
Connection connection = Util.getConnection();
// 获取hbase的namespace的操作对象
Admin admin = connection.getAdmin();
// 调用更改名字空间属性的方法
modifyNameSpace(admin);
// 关闭连接
admin.close();
connection.close();
}
/**
* 修改 namespace 的属性
* @param admin
*/
public static void modifyNameSpace(Admin admin) throws IOException {
// 获取更改'hbase04'的属性的构造器对象
NamespaceDescriptor.Builder hbase04 = NamespaceDescriptor.create("hbase04");
// 调用构造器里面封装的方法添加一个新的属性
hbase04.addConfiguration("day","2020-08-28");
// 调用构造器里面封装的方法移除一个属性
hbase04.removeConfiguration("ctime");
// 构造器对象调用构建方法 ,返回一个名字空间构建对象
NamespaceDescriptor namespaceDescriptor = hbase04.build();
// 操作对象调用修改方法 ,并将修改好的构建对象放到修改名字空间方法里面
admin.modifyNamespace(namespaceDescriptor);
}
/**
* 创建名称空间/namespace
*/
public static void createNameSpace(){
try {
// 获取连接对象
Connection conn = HbaseUtil.getHbaseConnection();
// 获取操作对象
Admin admin = conn.getAdmin();
//获取namespace对象
NamespaceDescriptor hbase = admin.getNamespaceDescriptor("hbase04");
//判断这个namespace是否存在
if(hbase != null){
//如果这个namespace存在 ,遍历namespace,将里面的table都取出来
TableName[] hbase01s = admin.listTableNamesByNamespace("hbase04");
for (TableName tableName : hbase01s) {
// 禁用表(禁用表后,才能对表进行删除/更新等操作)
admin.disableTable(tableName);
// 删除表
admin.deleteTable(tableName);
}
// 删除 namespace
admin.deleteNamespace("hbase04");
}
// 获取名称空间的构建器对象
NamespaceDescriptor.Builder hbase1 = NamespaceDescriptor.create("hbase04");
//设置namespace的属性信息
Map<String, String> map = new HashMap<>();
map.put("author","cch");
map.put("ctime",System.currentTimeMillis()+"");
hbase1.addConfiguration(map);
// 构造器对象调用构建方法,返回/获取构建对象
NamespaceDescriptor build = hbase1.build();
//创建名称空间
admin.createNamespace(build);
//关闭连接
admin.close();
conn.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
4 操作table(创建表/更新属性/删除表)
/**
* @Description : 操作table
**/
public class TableClient {
public static void main(String[] args) throws IOException {
createTable();
tableSplit();
}
// 创建表的方法
public static void createTable(){
try{
//获得链接对象
Connection connection = HbaseUtil.getHbaseConnection();
//获取操作对象
Admin admin = connection.getAdmin();
// 获取创建表的构造器
TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(TableName.valueOf("ns_order:tb_user"));
// 创建一个list集合,用来装 列族
List<ColumnFamilyDescriptor> list = new ArrayList<>();
// 需要添加列族 ,需要获取列族构造器对象
// 获取列族1构造器
ColumnFamilyDescriptorBuilder familyDescriptorBuilder = ColumnFamilyDescriptorBuilder.newBuilder("cf1".getBytes());
// 列族构造器对象设置属性
familyDescriptorBuilder.setTimeToLive(240);
familyDescriptorBuilder.setMaxVersions(3);
// 设置属性完毕后获取列族1构建对象
ColumnFamilyDescriptor family1Build = familyDescriptorBuilder.build();
// // 获取创建列族2的构造器
ColumnFamilyDescriptorBuilder familyDescriptorBuilder1 = ColumnFamilyDescriptorBuilder.newBuilder("cf2".getBytes());
// 列族2 设置属性
familyDescriptorBuilder1.setMaxVersions(3);
familyDescriptorBuilder1.setTimeToLive(240);
// 列族2 获取构建对象
ColumnFamilyDescriptor family2Build = familyDescriptorBuilder1.build();
// 将设置完成的列族并且获取了构建对象的列族放到集合里面
list.add(family1Build);
list.add(family2Build);
// 将装有列族的集合放到设置列族方法里面
builder.setColumnFamilies(list);
// 表构造器对象获取构建对象
TableDescriptor tablebuild = builder.build();
admin.createTable(tablebuild);
}catch (Exception e) {
e.printStackTrace();
}
}
/**
* 创建一个预分region的表
* 为了避免插入热点问题 ,将key进行切割split
* @param admin
*/
public static void tableSplit(){
try {
// 获取连接对象
Connection connection = HbaseUtil.getHbaseConnection();
// 获取操作对象
Admin admin = connection.getAdmin();
// 获取表构造器对象
TableDescriptorBuilder builder = TableDescriptorBuilder.newBuilder(TableName.valueOf("tb_web"));
// 获取表列族构造器对象
ColumnFamilyDescriptorBuilder familyDescriptorBuilder = ColumnFamilyDescriptorBuilder.newBuilder("cf".getBytes());
// 获取表列族构建对象
familyDescriptorBuilder.setTimeToLive(60*60*24*7);
familyDescriptorBuilder.setMaxVersions(3);
ColumnFamilyDescriptor familyBuild = familyDescriptorBuilder.build();
// 表构造器需要将列族信息设置
builder.setColumnFamily(familyBuild);
// 获取表构建对象
TableDescriptor build = builder.build();
// 获取切割点 ,按照字典顺序,指定三个切割点,切分成4个区
byte[][] keys = new byte[][]{"e".getBytes(),"g".getBytes(),"h".getBytes()};
// 创建表
admin.createTable(build,keys);
// 关闭连接
admin.close();
connection.close();
} catch (IOException e) {
e.printStackTrace();
}
}
// 封装判断表是否存在的方法
public static void isTableExists(Admin admin) throws IOException {
// 指定 namespace 下是否有指定的表
admin.tableExists(TableName.valueOf("hbase01:tb_user"));
// 默认的 namespace 下是否有表
admin.tableExists(TableName.valueOf("tb_user"));
}
}
为了避免热点插入问题 ,创建预分region的表 ,将keys进行指定切割点切分 .
按照字典的顺序 / ASCLL码表..指定切割点进行 regions 的切割 ,上述是按照指定的 'e' 'g' 'h' 三个指定的字母进行切分 ,一共切分成四个区 ,得到四个 region .
list_regions 'tb_web' // 查看创建的指定的表的 regions 个数
// 结果很明显 ,创建的表 'tb_web' 被切分为四个区 ,分别存储在 hbase 集群中的不同节点上
linux03,16020,1598542043871 | tb_web,,1598740852699.0a8f4f923e2af28a23dc117845219eac. | | e | 0 | 0 |0.0 |
linux05,16020,1598542042061 | tb_web,e,1598740852699.f3e626cf00fc5f95b23ce94ebc74da8c. | e | g | 0 | 0 | 0.0 |
linux04,16020,1598542041507 | tb_web,g,1598740852699.184e42a850fda74b771d9890a3f5dab0. | g | h | 0 | 0 | 0.0 |
linux03,16020,1598542043871 | tb_web,h,1598740852699.009c16914ad16579c906c5ff4f11b00b. | h | | 0 | 0 | 0.0 |
构造器 builder 注释 :
当进行 createTable / createNamespace / modifiyNamespace 等等操作时,需要使用到构造器 .
构造器被封装 ,里面有各种方法(有各种逻辑代码/可以实现各种功能), 通过new一个构造器对象来调用这些方法, 然后对namespace / table / 列族(columnfamily)等进行一系列操作 ,最后构造器对象调用构建方法 ,返回描述构建对象 ,然后之前获取的操作对象adnin(对namespace /table属性,结构进行操作的对象)调用createTable() / createNamespace() / modifiyNamespace()等方法,并将描述构建对象放进去 .