一、介绍   

        因为代驾过程中,需要保存驾驶途中的 GPS 定位,将来计算代驾真实里程的时候,就需要用到这些坐标点。那么这些定位点保存在 MySQL 中可以吗?当然不行,MySQL 单表记录超过两千万就卡的不行。那么保存在 MongoDB 中可以吗?也不行,因为 MongoDB 里面的条件查询真的是超级蹩脚,所以想要用复杂条件检索数据,还是打消用 MongoDB 的念头吧。

        除了 GPS 定位数据之外,还要把代驾过程中的聊天对话的文字内容保存起来。这么看来,我们需要一个既能保存海量数据,又能支持复杂条件检索的数据存储平台。HBase就再合适不过了。

        HBase是一个分布式、版本化、面向列的开源数据库。构建在 Apache Hadoop 和 Apache ZooKeeper 之上。HBase 是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统。利用 HBase 技术可在廉价的 PC server 上搭建大规模结构化存储集群。HBase 不同于一般的关系数据库,它是一个适合于非结构化数据存储的数据库,HBase 是基于列的,而不是基于行的模式。

        HBase特点:准实时查询(百豪秒以内);高可靠性,数据存储于HDFS中且依赖于 ZooKeeper进行 Master 和 RegionServer 的协调管理。

        HBase的操作语句很难写。

        Phoenix 是给 HBase 添加了一个语法表示层,允许我们用 SQL 语句读写 HBase 中的数据,可以做联机事务处理。拥有低延迟的特性,这就让我们方便多了。Phoenix 会把 SQL 编译成一系列的 HBase 的 scan 操作,然后把 scan 结果生成标准的 JDBC 结果集。处理千万级行的数据也只用毫秒或秒级就搞定。而且 Phoenix 还支持 MyBatis 框架,正好可以和华夏代驾项目整合到一起。

二、部署 HBase 和 Phoenix

1. 倒入镜像文件

        首先找到 HBase.tar.gz phoenix.tar.gz 镜像文件,然后把这个文件上传到 CentOS系统中,执行命令,把镜像文件导入 Docker 之中。

docker load < phoenix.tar.gz

2. 创建容器

        由于 HBase 需要使用的内存较大,这里我没有规定具体的内存大小,容器会自动使用空闲的内存。容器中数据目录是 /tmp/hbase-root/hbase/data ,把这个目录映射到宿主机的 /root/hbase/data 目录。

docker run -it -d -p 2181:2181 -p 8765:8765 -p 15165:15165 \
-p 16000:16000 -p 16010:16010 -p 16020:16020 \ #映射端口
-v /root/hbase/data:/tmp/hbase-root/hbase/data \ #映射文件
--name phoenix --net mynet --ip 172.18.0.14 \ #分配网络
boostport/hbase-phoenix-all-in-one:2.0-5.0 #镜像名字

 3. 开放端口

        使用 VirtualBox 软件把 Linux 的 2181、8765、15165、16000、16010、16020端口,映射到 Windows 的相应端口上面。

        参考链接:

4. 初始化Phoenix

        运行命令,进入到 Phoenix 容器中,然后执行命令设置 HBASE_CONF_DIR 环境变量。

docker exec -it phoenix bash

export HBASE_CONF_DIR=/opt/hbase/conf/

 然后就可以使用 Phoenix 自带的命令行客户端通过 SQL 语句操作 HBase数据。

        接下来我们要连接 Phoenix 的命令行客户端。虽然 IDEA 也内置了Phoenix 客户端,但是 Bug 挺多的,用着不方便。所以建议大家使用 Phoenix 自带的命令行客户端更好一些。而且我们要执行的 SQL 语句也并不多,命令行客户端已经足够用了。

/opt/phoenix-server/bin/sqlline.py localhost
#调用 Phoenix 自带的命令行客服端

三、创建逻辑库和数据表

1. 创建逻辑库

        为了存储数据,我们需要像操作 MySQL 一样,先创建逻辑库,再定义数据表。在 Phoenix 的命令行客户端,我们先来执行创建逻辑库的命令。

CREATE SCHEMA hxds #创建

USE hxds #切入

2. 创建数据表

        接下来我们要创建 order_voice_text、order_monitoring 和 order_gps 数据表。其中 order_voice_text 表用于存放司乘对话内容的文字内容;

CREATE TABLE hxds.order_voice_text(
    "id" BIGINT NOT NULL PRIMARY KEY, #只能主键加 NOT NULL
    "uuid" VARCHAR,
    "order_id" BIGINT,
    "record_file" VARCHAR,
    "text" VARCHAR,
    "label" VARCHAR,
    "suggestion" VARCHAR,
    "keywords" VARCHOR,
    "create_time" DATE
);

# ovt 为 order_voice_text 的缩写
#创建自增长的序列
CREATE SEQUENCE hxds.ovt_sequence START WITH 1 INCREMENT BY 1;

#给字段创建索引
CREATE INDEX ovt_index_1 ON hxds.order_voice_text("uuid");
CREATE INDEX ovt_index_2 ON hxds.order_voice_text("order_id");
CREATE INDEX ovt_index_3 ON hxds.order_voice_text("label");
CREATE INDEX ovt_index_4 ON hxds.order_voice_text("suggestion");
CREATE INDEX ovt_index_5 ON hxds.order_voice_text("create_time");

        order_monitoring 表存储 AI 分析对话内容的安全评级结果。命令类似于上面。

        order_gps 表存储代驾过程中的 GPS 定位。命令类似于上面。

#演示查询语句
SELECT * FROM hxds.order_gps;
SELECT * FROM hxds.order_gps WHERE "id"=9527;

 四、编写 hxds-nebula 子系统

        先来看一下 hxds-nebula 子系统的 application.yml 文件,里面的 JDBC 驱动和 URL 路径都是为了连接 Phoenix 的。如果你用的是云主机,别忘了 URL 要写云主机的 IP,而且还要在安全组里面把相关端口开放一下。

datasource:
    #驱动类
    driver-class-name: org.apache.phoenix.queryserver.client.Driver
    url: jdbc:phoenix:thin:url=http://127.0.0.1:8765;serialization=PROTOBUF
    type: com.alibaba.druid.pool.DruidDataSource
    druid:
        test-on-borrow: true
        test-while-idle: true
        max-active: 8
        min-idle: 4

1. 定义 POJO 类

        既然要用 MyBatis 连接 Phoenix,那么持久层的 POJO 类、DAO 接口和 XML 文件都要配齐了才可以。在 com.example.hxds.nebula.db.pojo 包中,创建3个 POJO 类。如下:

@Data
public class OrderMonitoringEntity {
    private Long id;
    private Long orderId;
    private Byte status;
    private Integer records;
    private String safety;
    private Integer reviews;
    private Byte alarm;
    private String createTime;
}

2. 定义 DAO 接口

        在 com.example.hxds.nebula.db.dao 包中,声明3个 DAO 接口。如下:

public interface OrderGpsDao {
    public int insert(OrderVoiceTextEntity entity)
}

3. 定义 XML 文件

        在 resources 目录中创建 mapper 文件夹,定义3个 XML 文件。如下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.example.hxds.nebula.db.dao.OrderGpsDao">
    <insert id="insert" parameterType="com.example.hxds.nebula.db.pojo.OrderVoiceTextEntity">
        UPSERT INTO hxds.order_voice_text("id", "uuid", "order_id", "record_file", "text", "create_time")
        VALUES(NEXT VALUE FOR hxds.ovt_sequence, '${uuid}', #{orderId}, '${recordFile}', '${text}', NOW())
    </INSERT>
</mapper>

4. 运行子系统

        上述内容都配置完成之后,就可以启动 hxds-nebula 子系统了,如果控制台没有报错信息,说明配置都是正确的。