Phoenix 是 HBase 的开源 SQL 皮肤,通过 Phoenix 可以使用标准 JDBC API 代替 HBase 客户端 API 来创建表,插入数据和查询 HBase 数据。
Phoenix 会把 SQL 编译成一系列的 Hbase 的 scan 操作,然后把 scan 结果生成标准的 JDBC 结果集,其底层由于使用了 Hbase 的API,协处理器,过滤器。Phoenix 支持的操作:SELECT, FROM、WHERE、GROUP BY、HAVING、ORDER BY 等。
Phoenix 其实就是一个客户端(或组件),它处于应用程序和 HBase 之间。Phoenix 客户端分为两种:
(1) 瘦客户端:将用户写好的 SQL 转交给 Phoenix Query 服务,由 Phoenix Query 服务把 SQL 解析成对应的HBase 操作,并交给 HBase 执行,执行完成之后并负责把结果收集回来,并转换成二维表格返回给用户。Phoenix Query 服务只针对瘦客户端。Phoenix Query 服务需要放到 HBase 的 RegionServer 里面。
(2) 胖客户端:不需要依赖 Phoenix Query 服务,客户端本身就可以完成 SQL 的解析和提交操作(连接 Zookeeper),建议用胖客户端,少一个需要维护的服务。
Phoenix 的特点:
(1) Phoenix 与 HBase 连接后会自动创建一些系统表, SYSTEM.CATALOG、SYSTEM.CHILD_LINK、SYSTEM.FUNCTION、SYSTEM.LOG、SYSTEM.MUTEX、SYSTEM.SEQUENCE、SYSTEM.STATS、SYSTEM.TASK,其中 SYSTEM.CATALOG 表用于存放 Phoenix 创建表时的元数据;
(2) Phoenix 创建表时会自动调用 HBase 客户端创建相应的表,并且在 SYSTEM.CATALOG 系统表中记录 Phoenix 创建表时的元数据,其主键的值对应 HBase 的 RowKey,非主键的列对应 HBase 的 Column(列族不指定时为0,且列会进行编码);
(3) Phoenix 的 SQL 中如果表名、字段名不使用双引号标注那么默认转换成大写,Phoenix 中的字符串使用单引号进行标注。默认情况下,库名,表名,字段名等会自动转换为大写,若要小写,使用双引号,如 "ns1",要特别注意引号的使用方式。
(4) 通过 Phoenix 创建的表,必须通过 Phoenix 客户端来对表进行操作,因为通过 Phoenix 创建的表其非主键的列会被编码;
Phoenix:https://phoenix.apache.org/
HBase 的安装配置,请参考 “Springboot 系列 (24) - Springboot+HBase 大数据存储(二)| 安装配置 Apache HBase 和 Apache Zookeeper”。
本文先介绍 Phoenix 组件的安装配置过程,再演示通过 Phoenix 组件使用 JDBC 访问 HBase。
1. 系统环境
操作系统:Ubuntu 20.04
Java 版本:openjdk 11.0.18
Hadoop 版本:3.2.2
Zookeeper 版本:3.6.3
HBase 版本:2.4.4
HBase 所在路径:~/apps/hbase-2.4.4
本文 HBase 在 HBase + Zookeeper (独立的) 模式下运行,Zookeeper 使用端口 2182。
2. 下载 Phoenix
访问 http://archive.apache.org/dist/phoenix/phoenix-5.1.2/phoenix-hbase-2.4-5.1.2-bin.tar.gz,下载 phoenix-hbase-2.4-5.1.2-bin.tar.gz 保存到 ~/apps 目录。
$ cd ~/apps
$ tar -zvxf phoenix-hbase-2.4-5.1.2-bin.tar.gz
$ mv phoenix-hbase-2.4-5.1.2-bin phoenix-5.1.2
$ cd phoenix-5.1.2
$ cp phoenix-server-hbase-2.4-5.1.2.jar ../hbase-2.4.4/lib # HBase 集群的 master 和 slave 都要复制该文件
3. 配置 Phoenix Schema 操作权限
$ cd ~/apps
# 修改 HBase 配置文件,添加如下内容
$ vim ./hbase-2.4.4/conf/hbase-site.xml
<property> <name>phoenix.schema.isNamespaceMappingEnabled</name> <value>true</value> </property> <property> <name>phoenix.schema.mapSystemTablesToNamespace</name> <value>true</value> </property>
# 修改 Phoenix 配置文件,添加如下内容
$ vim ./phoenix-5.1.2/bin/hbase-site.xml
<property> <name>phoenix.schema.isNamespaceMappingEnabled</name> <value>true</value> </property> <property> <name>phoenix.schema.mapSystemTablesToNamespace</name> <value>true</value> </property>
# 重启 HBase
$ cd ~/apps
# 停止 HBase
$ ./hbase-2.4.4/bin/stop-hbase.sh
# 启动 HBase
$ ./hbase-2.4.4/bin/start-hbase.sh
4. Phoenix Shell (Python)
$ cd ~/apps
$ ./phoenix-5.1.2/bin/sqlline.py localhost:2182 # localhost:2182 是 Zookeeper 的地址和端口
... Connected to: Phoenix (version 5.1) Driver: PhoenixEmbeddedDriver (version 5.1) Autocommit status: true Transaction isolation: TRANSACTION_READ_COMMITTED sqlline version 1.9.0 # 创建 schema (就是 HBase 中的 Namespace,相当于 RDBMS 的数据库) 0: jdbc:phoenix:localhost:2182> CREATE schema IF NOT EXISTS "ns_test"; # 切换 schema,如果不执行 USE "ns_test",那默认操作的是 “default” schema 0: jdbc:phoenix:localhost:2182> USE "ns_test"; # 删除 schema 0: jdbc:phoenix:localhost:2182> drop schema "ns_test"; # 创建表 0: jdbc:phoenix:localhost:2182> CREATE TABLE IF NOT EXISTS user ( . . . . . . . . . . . . . . .)> id varchar PRIMARY KEY, . . . . . . . . . . . . . . .)> name varchar, . . . . . . . . . . . . . . .)> age integer); # 查看 Phoenix 创建的所有表 0: jdbc:phoenix:localhost:2182> !tables +-----------+-------------+------------+--------------+---------+-----------+--- ... | TABLE_CAT | TABLE_SCHEM | TABLE_NAME | TABLE_TYPE | REMARKS | TYPE_NAME | +-----------+-------------+------------+--------------+---------+-----------+--- | | SYSTEM | CATALOG | SYSTEM TABLE | | | | | SYSTEM | CHILD_LINK | SYSTEM TABLE | | | | | SYSTEM | FUNCTION | SYSTEM TABLE | | | | | SYSTEM | LOG | SYSTEM TABLE | | | | | SYSTEM | MUTEX | SYSTEM TABLE | | | | | SYSTEM | SEQUENCE | SYSTEM TABLE | | | | | SYSTEM | STATS | SYSTEM TABLE | | | | | SYSTEM | TASK | SYSTEM TABLE | | | | | ns_test | USER | TABLE | | | +-----------+-------------+------------+--------------+---------+-----------+--- # 插入/更新数据 0: jdbc:phoenix:localhost:2182> UPSERT INTO user VALUES ('1', 'Tom', 12); 0: jdbc:phoenix:localhost:2182> UPSERT INTO user(id,name,age) VALUES ('2', 'Jerry', 10); 注: 如果主键的值重复,那么进行更新操作,否则插入一条新的记录。在使用 UPSERT 时,主键的列不能为空(包括联合主键)。 # 查询数据 0: jdbc:phoenix:localhost:2182> SELECT * FROM user; +----+-------+-----+ | ID | NAME | AGE | +----+-------+-----+ | 1 | Tom | 12 | | 2 | Jerry | 10 | +----+-------+-----+ 2 rows selected (0.066 seconds) 注:查询支持 ORDER BY、GROUP BY、LIMIT、JOIN 等操作,同时 Phoenix 提供了 COUNT()、MAX()、MIN()、SUM() 等函数。 函数列表可以查看:http://phoenix.apache.org/language/functions.html # 删除表 0: jdbc:phoenix:localhost:2182> DROP TABLE user; # 退出 sqlline,可以运行 !exit 或 !quit 或 !q 0: jdbc:phoenix:localhost:2182> !exit
Phoenix SQL 相关文档: https://phoenix.apache.org/language/index.html
5. 创建 Springboot 项目
Windows版本:Windows 10 Home (20H2)
IntelliJ IDEA:Community Edition for Windows 2020.1.4
Apache Maven:3.8.1
注:Spring 开发环境的搭建,可以参考 “ Spring基础知识(1)- Spring简介、Spring体系结构和开发环境配置 ”。
1) 运行 IDEA 创建项目
点击菜单 New 创建 Project:
New Project -> Project Type: Maven -> Project SDK: 1.8 -> Check "Create from archtype" -> select "org.apache.maven.archtypes:maven-archtype-quickstart" -> Next
Name: SpringbootExample23
GroupId: com.example
ArtifactId: SpringbootExample23
-> Finish
2) 修改 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.example</groupId> <artifactId>SpringbootExample23</artifactId> <version>1.0-SNAPSHOT</version> <name>SpringbootExample23</name> <!-- FIXME change it to the project's website --> <url>http://www.example.com</url> <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> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.6.6</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.11</version> <scope>test</scope> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <configuration> <mainClass>com.example.App</mainClass> <layout>JAR</layout> </configuration> <executions> <execution> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults (may be moved to parent pom) --> <plugins> ... </plugins> </pluginManagement> </build> </project>
在IDE中项目列表 -> SpringbootExample23 -> 点击鼠标右键 -> Maven -> Reload Project
本文选择了 spring-boot-starter-parent 2.6.6 相关依赖包,spring-boot-starter 和 spring-boot-starter-test 的版本由 spring-boot-starter-parent 控制。
3) 修改 src/main/java/com/example/App.java 文件
package com.example; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); System.out.println("Spring boot jar empty project"); } }
4) 添加 src/main/resources/application.properties 文件
spring.main.banner-mode=off
5) 运行
Run -> Edit configurations -> Click "+" -> Select "Maven"
Command line: clean spring-boot:run
Name: SpringbootExample23 [clean,spring-boot:run]
-> OK
Run -> Run "SpringbootExample23 [clean,spring-boot:run]"
Spring boot jar empty project
6. 添加 Phoenix 依赖
1) 修改 pom.xml,添加如下内容
<project ... > ... <dependencies> ... <dependency> <groupId>org.apache.phoenix</groupId> <artifactId>phoenix-core</artifactId> <version>5.1.2</version> <exclusions> <exclusion> <groupId>org.slf4j</groupId> <artifactId>slf4j-log4j12</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.apache.phoenix</groupId> <artifactId>phoenix-hbase-compat-2.4.1</artifactId> <version>5.1.2</version> <scope>runtime</scope> </dependency> </dependencies> </project>
注:phoenix-core、phoenix-hbase-compat 和 HBase 三者之间的版本必须兼容,phoenix-core 和 phoenix-hbase-compat 的版本要一致(或兼容),phoenix-hbase-compat-2.4.1 匹配的是 HBase 2.4.1+ (本文使用 HBase 2.4.4,在匹配范围内)。
在IDE中项目列表 -> SpringbootExample23 -> 点击鼠标右键 -> Maven -> Reload Project
2) 复制 hbase-site.xml 文件
把 phoenix-5.1.2/bin/hbase-site.xml 文件复制到项目 src/main/resources/hbase-site.xml,文件内容如下:
<configuration> <property> <name>hbase.regionserver.wal.codec</name> <value>org.apache.hadoop.hbase.regionserver.wal.IndexedWALEditCodec</value> </property> <property> <name>phoenix.schema.isNamespaceMappingEnabled</name> <value>true</value> </property> <property> <name>phoenix.schema.mapSystemTablesToNamespace</name> <value>true</value> </property> </configuration>
7. Phoenix JDBC 示例
在上文 Phoenix Shell 部分,我们在 HBase 里创建了一个 user 表,示例将使用 Phoenix JDBC 访问 user 表。
1) 修改 src/test/com/example/App.java 文件
package com.example; import java.sql.*; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; @SpringBootApplication public class App { public static void main(String[] args) { SpringApplication.run(App.class, args); Connection conn = null; try { Class.forName("org.apache.phoenix.jdbc.PhoenixDriver"); conn = DriverManager.getConnection("jdbc:phoenix:localhost:2182"); String sql = "SELECT * FROM user"; PreparedStatement preparedStatement = conn.prepareStatement(sql); ResultSet rs = preparedStatement.executeQuery(); System.out.println(sql); while (rs.next()) { System.out.println("name: " + rs.getString("name") + ", age: " + rs.getString("age")); } rs.close(); conn.close(); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (SQLException e) { e.printStackTrace(); } finally { if (conn != null) { try { conn.close(); } catch (SQLException e) { } } } } }
2) 打包 jar
菜单 View -> Tool Windows -> Maven -> SpringbootExample23 -> Lifecycle -> Clean & Package
jar 包生成在目录 target/ 里
SpringbootExample23-1.0-SNAPSHOT.jar
SpringbootExample23-1.0-SNAPSHOT.jar.original
SpringbootExample23.jar 包含依赖包,可以直接运行。 SpringbootExample23.jar.original 里不包含依赖的包(要手动配置依赖环境),运行前要把文件名上的 “.original” 去掉。
3) 运行 jar
本文 HBase 2.4.4 在 Ubuntu 20.04 主机的 ~/apps 目录。
把 SpringbootExample23-1.0-SNAPSHOT.jar 文件复制到 ~/apps 目录下,运行如下命令:
$ java -jar SpringbootExample23-1.0-SNAPSHOT.jar
... SELECT * FROM user name: Tom, age: 12 name: Jerry, age: 10 2023-04-05 12:07:28.415 INFO 25762 --- [2182@0x386f0da3] org.apache.zookeeper.ZooKeeper : Session: 0x100013e3e800013 closed 2023-04-05 12:07:28.415 INFO 25762 --- [da3-EventThread] org.apache.zookeeper.ClientCnxn : EventThread shut down for session: 0x100013e3e800013
标签:JDBC,Springboot,phoenix,Phoenix,boot,SYSTEM,HBase,hbase From: https://www.cnblogs.com/tkuang/p/17289261.html