08-HBase环境搭建

星期一, 4月 7, 2025 | 7分钟阅读

MyraZ
08-HBase环境搭建

关于Linux系统大数据环境搭建——08-HBase环境搭建。

08-HBase环境搭建

HBase版本:HBase2.5.3

集群搭建

目标环境

image-20250320194705348

前提:Hadoop 正常运行,ZooKeeper 正常运行,Hive 正常运行,服务器时间同步。

安装

解压

​ 将准备好的安装包上传至 node01,然后解压:

[root@node01 ~]# tar -zxvf hbase-2.5.3-bin.tar.gz -C /opt/yjx/
[root@node01 ~]# rm hbase-2.5.3-bin.tar.gz -rf

修改配置文件

​ 修改环境配置文件 hbase-env.sh

[root@node01 ~]# cd /opt/yjx/hbase-2.5.3/conf/
[root@node01 conf]# vim hbase-env.sh

​ 在文件末尾添加以下内容:

export JAVA_HOME=/usr/java/jdk1.8.0_351-amd64
export HADOOP_HOME=/opt/yjx/hadoop-3.3.4/
export HBASE_MANAGES_ZK=false
export HBASE_LOG_DIR=${HBASE_HOME}/logs
# HBase 的 Jar 包和 Hadoop 的 Jar 包会有冲突,会导致服务启动失败。设置以下参数禁止启动时扫描 Hadoop 的 Jar包
export HBASE_DISABLE_HADOOP_CLASSPATH_LOOKUP="true"

​ 修改配置文件 hbase-site.xml

[root@node01 conf]# vim hbase-site.xml
	首先删除 `configuration` 节点中的所有内容,然后再在 `configuration `节点中添加以下内容:  
<!-- 设置 HBase 数据存储的位置(存储在 HDFS 上的位置) -->
<!-- 使用本地文件系统例如:file:///root/hbase/data -->
<property>
<name>hbase.rootdir</name>
<value>hdfs://hdfs-yjx/hbase</value>
</property>
<!-- 是否为分布式模式部署,true 表示分布式部署 -->
<property>
<name>hbase.cluster.distributed</name>
<value>true</value>
</property>
<!-- 设置 HBase 的 ZK 集群地址,以逗号分隔 -->
<property>
<name>hbase.zookeeper.quorum</name>
<value>node01,node02,node03:2181</value>
</property>
<!-- 设置 HBase 在 ZK 上的数据根目录 znode 节点名称 -->
<property>
<name>zookeeper.znode.parent</name>
<value>/hbase</value>
</property>
<!-- 本地文件系统的临时目录,默认在 /tmp,/tmp 会在服务器重启时被清除,一般配置成本地文件模式时才需要设置 -->
<property>
<name>hbase.tmp.dir</name>
<value>/var/yjx/hbase</value>
</property>
<!-- 控制 HBase 是否检查流功能(hflush/hsync),如果要在 HDFS 系统上运行,请禁用此选项 -->
<!-- 简单的理解就是:使用 HDFS 存储将其设置为 false,使用本地文件系统将其设置为 true -->
<property>
<name>hbase.unsafe.stream.capability.enforce</name>
<value>false</value>
</property>

​ 修改 regionservers

[root@node01 conf]# vim regionservers

​ 用以下内容替换文件内容:

node01   
node02   
node03

​ 添加备用主机 backup-masters

[root@node01 conf]# vim backup-masters

​ 用以下内容替换文件内容:

node02

​ 拷贝 Hadoop 配置文件至 HBase。

[root@node01 conf]# cp /opt/yjx/hadoop-3.3.4/etc/hadoop/core-site.xml /opt/yjx/hbase-2.5.3/conf/
[root@node01 conf]# cp /opt/yjx/hadoop-3.3.4/etc/hadoop/hdfs-site.xml /opt/yjx/hbase-2.5.3/conf/

拷贝至其他节点

​ 将 node01 已配置好的 HBase 拷贝至 node02 和 node03。

[root@node02 ~]# scp -r root@node01:/opt/yjx/hbase-2.5.3 /opt/yjx/
[root@node03 ~]# scp -r root@node01:/opt/yjx/hbase-2.5.3 /opt/yjx/
# 或者使用分发脚本
[root@node01 ~]# yjxrsync /opt/yjx/hbase-2.5.3

修改环境变量

​ 三个节点修改环境变量 vim /etc/profile ,在文件末尾添加以下内容:

export HBASE_HOME=/opt/yjx/hbase-2.5.3
export PATH=$HBASE_HOME/bin:$PATH

​ 修改完成后 source /etc/profile 重新加载环境变量。

启动

​ 启动 ZooKeeper(三台机器都需要执行)。

zkServer.sh start 
zkServer.sh status  

​ 启动 HDFS。

[root@node01 \~]# start-all.sh  

​ 启动 HBase。

[root@node01 \~]# start-hbase.sh 

访问

​ 先使用jps命令查看各节点服务运行情况。

image-20250320195615563 Web 访问:http://node01:16010 结果如下。

image-20250320195659331

​ Web 访问:http://node02:16010 结果如下。

image-20250320195736391

关闭

​ 先关闭 HBase。

[root@node01 ~]# stop-hbase.sh

​ 再关闭 HDFS。

[root@node01 ~]# stop-all.sh

​ 再关闭 ZooKeeper(三台机器都需要执行)。

zkServer.sh stop

​ 环境搭建成功后删除安装包, shutdown -h now 关机拍摄快照。

框架整合

HBase 和 MapReduce

添加依赖

​ 在之前的 hbase-demo 项目中添加hbase-mapreduce依赖。

<dependency>
    <groupId>org.apache.hbase</groupId>
    <artifactId>hbase-mapreduce</artifactId>
    <version>${hbase.version}</version>
</dependency>

​ 完整 pom.xml 文件如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.yjxxt</groupId>
    <artifactId>hbase-demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <!-- Hadoop 版本控制 -->
        <hadoop.version>3.3.4</hadoop.version>
        <!-- HBase 版本控制 -->
        <hbase.version>2.5.3</hbase.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-client</artifactId>
            <version>${hadoop.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-hdfs</artifactId>
            <version>${hadoop.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hadoop</groupId>
            <artifactId>hadoop-auth</artifactId>
            <version>${hadoop.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-client</artifactId>
            <version>${hbase.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-server</artifactId>
            <version>${hbase.version}</version>
        </dependency>
        <dependency>
            <groupId>org.apache.hbase</groupId>
            <artifactId>hbase-mapreduce</artifactId>
            <version>${hbase.version}</version>
        </dependency>

        <!-- JUnit 单元测试 -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-api</artifactId>
            <version>5.9.2</version>
            <scope>test</scope>
        </dependency>
    </dependencies>

</project>

创建数据库

​ 将 harry potter.txt 文件上传至 HDFS 的 /yjx/harry potter.txt
​ 在 HBase 中创建 t_wordcount 表并添加 word 列族。

hbase> create 't_wordcount', 'word'

Hdfs2HBase

​ 编写 Job、Mapper、Reducer。

	Hdfs2HBaseWordCountJob.java
package com.yjxxt.hbase.mapred.hdfs2hbase;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.input.FileInputFormat;

import java.io.IOException;

public class Hdfs2HBaseWordCountJob {

    public static void main(String[] args) throws IOException,
            InterruptedException, ClassNotFoundException {
        // 加载配置文件
        Configuration configuration = HBaseConfiguration.create();
        // 本地模式运行
        configuration.set("mapreduce.framework.name", "local");
        // 创建作业并设置作业名称
        Job job = Job.getInstance(configuration, "yjx-hdfs2hbase-" + System.currentTimeMillis());
        // 设置作业主类
        job.setJarByClass(Hdfs2HBaseWordCountJob.class);
        // 设置 Reduce 的数量
        job.setNumReduceTasks(2);
        // 设置数据的输入路径(需要计算的数据从哪里读)
        FileInputFormat.setInputPaths(job, new Path("/yjx/harry potter.txt"));
        // 设置 Map 的输出的 Key 和 Value 的类型
        job.setMapOutputKeyClass(Text.class);
        job.setMapOutputValueClass(IntWritable.class);
        // 设置 Map 的处理类
        job.setMapperClass(Hdfs2HBaseWordCountMapper.class);
        // 设置 Reduce 写出到 HBase 的数据库
        TableMapReduceUtil.initTableReducerJob("t_wordcount",
                Hdfs2HBaseWordCountReducer.class, job, null, null, null, null, false);
        job.waitForCompletion(true);
    }

}

​ Hdfs2HBaseWordCountMapper.java

package com.yjxxt.hbase.mapred.hdfs2hbase;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.LongWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Mapper;

import java.io.IOException;

public class Hdfs2HBaseWordCountMapper extends Mapper<LongWritable, Text, Text, IntWritable> {

    private IntWritable one = new IntWritable(1);

    /**
     * @param key     前行的偏移量
     * @param value   当前行的数据
     * @param context 可以理解为环形数据缓冲区
     * @throws IOException
     * @throws InterruptedException
     */
    @Override
    protected void map(LongWritable key, Text value, Context context)
            throws IOException, InterruptedException {
        // 替换特殊字符
        String line = value.toString().replaceAll("[^\\w'-]+", " ");
        // 切分字符串
        String[] words = line.split("\\s+");
        // 写出数据
        for (String word : words) {
            context.write(new Text(word), one);
        }
    }

}

​ Hdfs2HBaseWordCountReducer.java

package com.yjxxt.hbase.mapred.hdfs2hbase;

import org.apache.hadoop.hbase.client.Put;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.TableReducer;
import org.apache.hadoop.hbase.util.Bytes;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;

import java.io.IOException;

public class Hdfs2HBaseWordCountReducer extends TableReducer<Text, IntWritable, ImmutableBytesWritable> {

    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Context context)
            throws IOException, InterruptedException {
        // 声明计数器
        int count = 0;
        // 循环处理
        for (IntWritable value : values) {
            count += value.get();
        }
        // 创建插入数据对象 Put
        // 初始化 RowKey
        Put put = new Put(Bytes.toBytes("harry_potter_" + key.toString()));
        // 列族和列
        put.addColumn(Bytes.toBytes("word"), Bytes.toBytes(key.toString()), Bytes.toBytes(String.valueOf(count)));
        // 写出数据
        context.write(null, put);
    }

}

HBase2Hdfs

Mock 数据

​ 使用以下程序生成一批随机的手机通话记录。

package com.yjxxt.phone;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.Cell;
import org.apache.hadoop.hbase.CellUtil;
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 org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;

@DisplayName("手机通话记录生成测试类")
public class PhoneRecordTest {

    /**
     * HBase 的管理对象
     */
    private Admin admin;
    /**
     * 数据库连接
     */
    private Connection connection;
    /**
     * 表对象
     */
    private Table table;
    /**
     * 表名
     */
    private final static String TABLE_NAME = "t_phone";
    /**
     * 列族
     */
    private final static String COLUMN_FAMILY_NAME = "info";

    @DisplayName("创建数据库连接并初始化管理类和数据库表")
    @BeforeEach
    public void init() throws IOException {
        // 初始化 HBase 配置类
        Configuration configuration = HBaseConfiguration.create();
        // 创建数据库连接
        connection = ConnectionFactory.createConnection(configuration);
        // 初始化 HBase 管理类
        admin = connection.getAdmin();
        // 获取数据库表
        table = connection.getTable(TableName.valueOf(TABLE_NAME));
    }

    @DisplayName("释放 HBase 资源")
    @AfterEach
    public void destory() throws IOException {
        if (table != null) {
            table.close();
        }
        if (admin != null) {
            admin.close();
        }
        if (connection != null) {
            connection.close();
        }
    }

    @DisplayName("创建含有预分区的表")
    @Test
    public void createTable() throws IOException {
        // 获取表
        TableDescriptorBuilder table = TableDescriptorBuilder.newBuilder(TableName.valueOf(TABLE_NAME));
        // 创建列族
        ColumnFamilyDescriptorBuilder columnBuilder = ColumnFamilyDescriptorBuilder.newBuilder(Bytes.toBytes(COLUMN_FAMILY_NAME));
        ColumnFamilyDescriptor familyDescriptor = columnBuilder.build();
        // 将列族添加到表对象
        table.setColumnFamily(familyDescriptor);
        // 获取预分区
        byte[][] phoneRange = createPhoneSplits();
        // 创建表对象
        admin.createTable(table.build(), phoneRange);
    }

    @DisplayName("批量插入手机通话记录")
    @Test
    public void putPhoneRecords() throws IOException {
        // 创建一个容器
        List<Put> puts = new ArrayList<>();
        // 批量插入数据
        for (int i = 0; i < 100; i++) {
            // 随机生成一个手机号码
            String phone = getRandomPhone();
            // 开始随机生成通话记录
            for (int j = 0; j < 100; j++) {
                // 随机生成数据
                String otherphone = getRandomPhone();
                Date date = getRandomDate();
                // 创建插入对象
                Put put = new Put(Bytes.toBytes(phone + "_" + date.getTime()));
                put.addColumn(Bytes.toBytes(COLUMN_FAMILY_NAME), Bytes.toBytes("otherphone"), Bytes.toBytes(otherphone));
                put.addColumn(Bytes.toBytes(COLUMN_FAMILY_NAME), Bytes.toBytes("time"), Bytes.toBytes(getRandomNum(1, 3600 * 3)));
                put.addColumn(Bytes.toBytes(COLUMN_FAMILY_NAME), Bytes.toBytes("date"), Bytes.toBytes(date.getTime()));
                put.addColumn(Bytes.toBytes(COLUMN_FAMILY_NAME), Bytes.toBytes("type"), Bytes.toBytes(String.valueOf(getRandomNum(0, 1))));
                // 添加至容器
                puts.add(put);
            }
        }
        // 将数据插入到数据库
        table.put(puts);
    }

    @DisplayName("扫描数据")
    @Test
    public void scanPhoneRecords() throws Exception {
        // 创建扫描对象
        Scan scan = new Scan();
        // 本次查询开始的 RowKey 和结束的 RowKey
        String startRow = "138";
        String endRow = "139";
        scan.withStartRow(Bytes.toBytes(startRow));
        scan.withStopRow(Bytes.toBytes(endRow));
        // 创建结果扫描器
        ResultScanner resultScanner = table.getScanner(scan);
        // 获取所有的结果
        for (Result result : resultScanner) {
            // 获取 Cell
            List<Cell> cells = result.listCells();
            for (Cell cell : cells) {
                String qualifier = Bytes.toString(CellUtil.cloneQualifier(cell));
                if (qualifier.equals("date")) {
                    System.out.println(Bytes.toString(CellUtil.cloneRow(cell)) + ":" + Bytes.toString(CellUtil.cloneFamily(cell)) + ":" + Bytes.toString(CellUtil.cloneQualifier(cell)) + ":" + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date(Bytes.toLong(CellUtil.cloneValue(cell)))));
                } else if (qualifier.equals("time")) {
                    System.out.println(Bytes.toString(CellUtil.cloneRow(cell)) + ":" + Bytes.toString(CellUtil.cloneFamily(cell)) + ":" + Bytes.toString(CellUtil.cloneQualifier(cell)) + ":" + Bytes.toInt(CellUtil.cloneValue(cell)));
                } else {
                    System.out.println(Bytes.toString(CellUtil.cloneRow(cell)) + ":" + Bytes.toString(CellUtil.cloneFamily(cell)) + ":" + Bytes.toString(CellUtil.cloneQualifier(cell)) + ":" + Bytes.toString(CellUtil.cloneValue(cell)));
                }
            }
        }
        resultScanner.close();
    }

    /**
     * 创建手机号码通讯记录表的预分区
     *
     * @return
     */
    private byte[][] createPhoneSplits() {
        String[] telArrays = "134,135,136,137,138,139,150,151,152,157,158,159,130,131,132,155,156,133,153".split(",");
        // 对数组进行排序
        Arrays.sort(telArrays);
        // 创建分区
        byte[][] phoneSplits = new byte[telArrays.length][];
        for (int i = 0; i < telArrays.length; i++) {
            phoneSplits[i] = Bytes.toBytes(telArrays[i]);
        }
        return phoneSplits;
    }

    /**
     * 随机生成手机号码
     *
     * @return
     */
    private static String getRandomPhone() {
        String[] telArrays = "134,135,136,137,138,139,150,151,152,157,158,159,130,131,132,155,156,133,153".split(",");
        int index = getRandomNum(0, telArrays.length - 1);
        String first = telArrays[index];
        String second = String.valueOf(getRandomNum(1, 888) + 10000).substring(1);
        String third = String.valueOf(getRandomNum(1, 9100) + 10000).substring(1);
        return first + second + third;
    }

    /**
     * 生成随机数字
     *
     * @param start
     * @param end
     * @return
     */
    public static int getRandomNum(int start, int end) {
        return (int) (Math.random() * (end - start + 1) + start);
    }

    /**
     * 随机获取日期
     *
     * @return
     */
    private static Date getRandomDate() {
        try {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            Date start = format.parse("2021-01-01");
            Date end = format.parse("2022-01-01");
            if (start.getTime() >= end.getTime()) {
                return null;
            }
            long date = random(start.getTime(), end.getTime());
            return new Date(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 随机生成数据
     *
     * @param begin
     * @param end
     * @return
     */
    private static long random(long begin, long end) {
        long rtn = begin + (long) (Math.random() * (end - begin));
        if (rtn == begin || rtn == end) {
            return random(begin, end);
        }
        return rtn;
    }

}
编码

​ 编写 Job、Mapper、Reducer。

​ HBase2HdfsPhoneJob.java

package com.yjxxt.hbase.mapred.hbase2hdfs;

import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.hbase.HBaseConfiguration;
import org.apache.hadoop.hbase.client.Scan;
import org.apache.hadoop.hbase.mapreduce.TableMapReduceUtil;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Job;
import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat;

import java.io.IOException;

public class HBase2HdfsPhoneJob {

    public static void main(String[] args) throws IOException,
            ClassNotFoundException, InterruptedException {
        // 加载配置文件
        Configuration configuration = HBaseConfiguration.create();
        // 本地模式运行
        configuration.set("mapreduce.framework.name", "local");
        // 创建作业并设置作业名称
        Job job = Job.getInstance(configuration, "yjx-hbase2hdfs-" + System.currentTimeMillis());
        // 设置当前任务的主类
        job.setJarByClass(HBase2HdfsPhoneJob.class);
        // 设置 Reduce 的数量
        job.setNumReduceTasks(2);
        // 设置数据的输出路径(计算后的数据输出到哪里)
        FileOutputFormat.setOutputPath(job, new Path("/yjx/result/" + job.getJobName()));
        // 设置扫描器
        Scan scan = new Scan();
        scan.withStartRow("138".getBytes());
        scan.withStopRow("139".getBytes());
        // 设置 Map 从 HBase 读取数据至 HDFS
        TableMapReduceUtil.initTableMapperJob("t_phone", scan,
                HBase2HdfsPhoneMapper.class, Text.class, IntWritable.class, job, false);
        // 设置 Reduce 的处理类
        job.setReducerClass(HBase2HdfsPhoneReducer.class);
        // 将作业提交到集群并等待完成
        job.waitForCompletion(true);
    }

}

​ HBase2HdfsPhoneMapper.java

package com.yjxxt.hbase.mapred.hbase2hdfs;

import org.apache.hadoop.hbase.client.Result;
import org.apache.hadoop.hbase.io.ImmutableBytesWritable;
import org.apache.hadoop.hbase.mapreduce.TableMapper;
import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;

import java.io.IOException;

public class HBase2HdfsPhoneMapper extends TableMapper<Text, IntWritable> {

    @Override
    protected void map(ImmutableBytesWritable key, Result value, Context context) throws IOException, InterruptedException {
        // 获取 RowKey 并分割处理得到手机号
        String rowkey = new String(value.getRow());
        String phoneNum = rowkey.split("_")[0];
        context.write(new Text(phoneNum), new IntWritable(1));
    }

}

​ HBase2HdfsPhoneReducer.java

package com.yjxxt.hbase.mapred.hbase2hdfs;

import org.apache.hadoop.io.IntWritable;
import org.apache.hadoop.io.Text;
import org.apache.hadoop.mapreduce.Reducer;

import java.io.IOException;

public class HBase2HdfsPhoneReducer extends Reducer<Text, IntWritable, Text, IntWritable> {

    @Override
    protected void reduce(Text key, Iterable<IntWritable> values, Context context)
            throws IOException, InterruptedException {
        int count = 0;
        for (IntWritable value : values) {
            count += value.get();
        }
        context.write(key, new IntWritable(count));
    }

}

HBase 和 Hive

​ Hive 提供了与 HBase 的集成,使得能够在 HBase 表上使用 HQL 语句进行查询、插入以及 JOIN、UNION 等复杂查询,同时也可以将 Hive 表中的数据映射到 HBase 中。

拷贝 Jar

​ 三台机器分别执行以下命令,将 hive-hbase-handler-3.1.2.jar 拷贝至 HBase。

cp /opt/yjx/apache-hive-3.1.2-bin/lib/hive-hbase-handler-3.1.2.jar /opt/yjx/hbase-2.5.3/lib/

​ 检查 Jar 包是否已经拷贝。

ls /opt/yjx/hbase-2.5.3/lib/hive-hbase-handler-3.1.2.jar

修改配置文件

​ 修改 Hive(MetaStore 机器) 的配置文件vim /opt/yjx/apache-hive-3.1.2-bin/conf/hive-site.xml,配置HBase 的 ZooKeeper 集群。

<property>
<name>hbase.zookeeper.quorum</name>
<value>node01:2181,node02:2181,node03:2181</value>
</property>

测试

​ HBase 创建 hbase_user 表并添加 info 列族。

# 创建 test 命令空间
create_namespace 'test'
# 创建 hbase_user 表并添加 info 列族
create 'test:hbase_user', 'info'
# 插入数据
put 'test:hbase_user', '1', 'info:name', 'zhangsan'
put 'test:hbase_user', '1', 'info:age', '18'
put 'test:hbase_user', '1', 'info:gender', 'male'
put 'test:hbase_user', '2', 'info:name', 'lisi'
put 'test:hbase_user', '2', 'info:age', '19'
put 'test:hbase_user', '2', 'info:gender', 'female'
put 'test:hbase_user', '3', 'info:name', 'wangwu'
put 'test:hbase_user', '3', 'info:age', '20'
put 'test:hbase_user', '3', 'info:gender', 'male'

​ Hive 创建 hive_user 外部表并使用 HBase 序列化器。

-- 创建 test 数据库
CREATE DATABASE IF NOT EXISTS test;
-- 创建 hive_user 外部表
CREATE EXTERNAL TABLE IF NOT EXISTS test.hive_user (
id string,
name string,
age string,
gender string
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.hbase.HBaseSerDe'
STORED BY 'org.apache.hadoop.hive.hbase.HBaseStorageHandler'
WITH SERDEPROPERTIES('hbase.columns.mapping'=':key,info:name,info:age,info:gender')
TBLPROPERTIES('hbase.table.name'='test:hbase_user');
-- 通过查询测试是否整合成功
SELECT * FROM test.hive_user;

© 2024 - 2025 雪中烛

 

在线工具资源网站

在线工具官网

ProcessOn:👉ProcessOn在线作图

腾讯文档:👉腾讯文档

FlowUs 息流:👉FlowUs 息流

Mermaid Live Editor:👉在线流程图和图表编辑器 - 美人鱼实时编辑器

ME2在线工具(加密工具):👉ME2在线工具-在线开发学习生活工具箱

Textln:👉Textln文本智能云平台-通用文本解析

MinerU:👉MinerU数据提取工具

Crontab:👉Cron Expression Examples - Crontab.guru

正则表达式测试网站:👉regex101: build, test, and debug regex

技术资源网站

技术资源官网

Spring:👉Spring官网

MyBatis中文网 :👉MyBatis 中文网

Redis中文网:👉Redis中文网

Zookeeper:👉Apache ZooKeeper官网

Raft算法:👉Raft Consensus Algorithm官网

Hadoop:👉Apache Hadoop官网

Hive:👉Apache Hive官网

Phoenix:👉Apache Phoenix官网

Bootstrap中文网:👉Bootstrap中文网

Element:👉组件 | Element

Layui :👉Layui - 极简模块化前端 UI 组件库(官方文档)

FreeMarker :👉FreeMarker 中文官方参考手册

ztree树插件: 👉zTree – jQuery 树插件官网

x File Storage:👉x File Storage官网