📢 大家好,我是 【战神刘玉栋】,有10多年的研发经验,致力于前后端技术栈的知识沉淀和传播。 💗
🌻 CSDN入驻不久,希望大家多多支持,后续会继续提升文章质量,绝不滥竽充数,欢迎多多交流。👍
文章目录
写在前面的话
前不久的一篇博文《技术栈选型之跨库查询分析》,介绍了博主所在公司的跨库查询背景,其中一个可选方案是通过数据库中间件来完成,诸如 ShardingSphere、Presto 都进行了尝试验证。
本篇文章主要介绍利用 ShardingSphere 联邦查询实现跨库查询的可行性,后续再针对其他技术点进行展开介绍。
技术简介
Apache ShardingSphere 是一款分布式 SQL 事务和查询引擎,可通过数据分片、弹性伸缩、加密等能力对任意数据库进行增强。
Apache ShardingSphere 是一款分布式的数据库生态系统,它包含两大产品:
ShardingSphere-Proxy
ShardingSphere-JDBC
这里可以直接参考ShardingSphere 官网,介绍的比较详细了。
ShardingSphere-JDBC
ShardingSphere-JDBC 定位为轻量级 Java 框架,在 Java 的 JDBC 层提供的额外服务。 它使用客户端直连数据库,以 jar 包形式提供服务,无需额外部署和依赖,可理解为增强版的 JDBC 驱动,完全兼容 JDBC 和各种 ORM 框架。
Tips:通俗一点,就是您的SpringBoot可以整合它,然后和操作JDBC一样操作它。
ShardingSphere-Proxy
ShardingSphere-Proxy 定位为透明化的数据库代理端,通过实现数据库二进制协议,对异构语言提供支持。 目前提供 MySQL 和 PostgreSQL 协议,透明化数据库操作,对 DBA 更加友好。
Tips:通俗一点,作为一个中间件那样部署在服务器上,您的程序连它就好了,正常执行SQL就好了,可以直接跨库。
两种模式对比
当我们在 Proxy 和 JDBC 两种模式选择时,可以参考下表对照(来自官网):
1、ShardingSphere-Proxy 提供静态入口以及异构语言的支持,独立于应用程序部署,适用于 OLAP 应用以及对分片数据库进行管理和运维的场景。
2、ShardingSphere-JDBC 采用无中心化架构,与应用程序共享资源,适用于 Java 开发的高性能的轻量级 OLTP 应用;
如果您的后端是Java,又想兼容大部分主流数据库,则使用JDBC;如果想尽量减轻程序猿的负担,都在服务端完成配置,则采用Proxy;按实际情况来选择吧。
【选择建议】
1、小型项目:如果项目较小,且对分片和读写分离的需求不高,可以选择 JDBC 模式。
2、大型企业级项目:如果项目复杂,涉及多个数据源和复杂的分片需求,建议使用 Proxy 模式,以便于管理和扩展。
3、对于新开发的应用程序,建议选择 Proxy 模式, 因为它对应用程序透明,易于维护和升级。
4、对于已经存在的应用程序,如果改造成本较高,可以选择 JDBC 模式,但需要评估其性能影响。
功能场景
ShardingSphere 是一个开源的分布式数据库中间件,提供了多种功能,除了联邦查询外,还有以下常用功能:
- 数据分片:支持水平分片和垂直分片,可以根据业务需求将数据分散到多个数据库中。
- 读写分离:支持将读请求和写请求分发到不同的数据库,以提高性能和可扩展性。
- 数据加密:提供数据加密功能,确保敏感数据的安全性。
- 分布式事务:支持两阶段提交(2PC)和最终一致性事务,确保分布式环境中的数据一致性。
- 动态扩容:支持在运行时动态添加或移除数据源,方便系统扩展。
- SQL解析与优化:提供SQL解析、优化和重写功能,以提高查询性能。
- 数据治理:提供数据脱敏、数据屏蔽、SQL 审计等功能,帮助用户进行数据治理和安全管控。
- 数据库治理:提供数据库监控、性能分析、慢 SQL 分析等功能,帮助用户进行数据库运维和性能优化。
- 监控与管理:提供监控接口,可以与监控工具集成,实时监控数据库性能。
- 多种数据库支持:支持多种关系型数据库,如 MySQL、PostgreSQL、Oracle 等。
本文主要介绍公司需求场景需要的联邦查询功能,但实际上 ShardingSphere 的联邦查询还在不断完善的阶段,对非MySQL和PostgreSQL的数据库情况,支持能力受限,例如Oracle的表空间问题。
不吹不黑,ShardingSphere 的数据分片、读写分离等主流功能,还是相当强大的。
实战说明
前言
由于ShardingSphere-JDBC模式更贴合公司需要,因此选择用这套尝试。
当然,ShardingSphere-Proxy 模式也尝试过,操作也很简单,支持二进制发布包和Docker部署方式,安装完成后,会默认启动一个MySQL,程序直接连这个MySQL,再通过修改配置文件的相关配置,即可实现联邦查询等功能。这边不是本文重点,就不展开赘述了。
项目实战
Step1、创建一个SpringBoot服务,引入相关依赖
主要是 shardingsphere-jdbc,至于各数据库驱动可以按需选择,针对ORM框架使用哪套,也按需选择。
xml
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
<version>5.1.1</version>
</dependency>
<!-- 各数据库的依赖 -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc8</artifactId>
<version>19.3.0.0</version>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
<scope>runtime</scope>
<version>42.6.2</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.2.9</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.3.1</version>
</dependency>
Step2、在application.yml调整ShardingSphere配置
yaml
spring:
# 应用名称
application:
name: sharding-jdbc-demo
# 环境设置
profiles:
active: dev
shardingsphere:
# 运行模式类型
# 可选配置:Memory、Standalone、Cluster
mode:
type: Memory
# 数据源配置,可配置多个
# ShardingSphere-JDBC 支持所有的数据库 JDBC 驱动和连接池。
datasource:
# 配置真实数据源
names: master,slave0,slave1,slave2
# 配置第 1 个数据源 t_dict_ex
master:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://xxxx:3306/demo0
username: root
password: lw1013
# 配置第 2 个数据源 lw_user
slave0:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://xxxx:3306/demo1
username: root
password: ~
# 配置第 3 个数据源 lw_phone
slave1:
type: com.zaxxer.hikari.HikariDataSource
driver-class-name: com.mysql.cj.jdbc.Driver
jdbc-url: jdbc:mysql://xxxx:3306/demo1
username: root
password: ~
# 打印SQL,支持联邦查询
props:
sql-show: true
sql-federation-enabled: true
Step3、正常编码使用ORM操作,可以看到日志输出信息
从日志也可以看出,确实从不同库加载了。
latex
2024-10-22 18:37:59.213 INFO 44048 - ShardingSphere-SQL : Logic SQL: SELECT lp.id, lp.phone, lp.user_id, lu.name, dict.dict_type FROM lw_phone lp LEFT JOIN lw_user lu ON lp.user_id = lu.id LEFT JOIN t_dict_ex dict ON dict.id = lp.phone limit 10
2024-10-22 18:37:59.213 INFO 44048 - ShardingSphere-SQL : SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional[org.apache.shardingsphere.sql.parser.sql.common.segment.dml.pagination.limit.LimitSegment@4390b78f], lock=Optional.empty, window=Optional.empty)
2024-10-22 18:37:59.213 INFO 44048 - ShardingSphere-SQL : Actual SQL: slave0 ::: SELECT lp.id, lp.phone, lp.user_id, lu.name, dict.dict_type FROM lw_phone lp LEFT JOIN lw_user lu ON lp.user_id = lu.id LEFT JOIN t_dict_ex dict ON dict.id = lp.phone limit 10
2024-10-22 18:37:59.213 INFO 44048 - ShardingSphere-SQL : Actual SQL: slave1 ::: SELECT lp.id, lp.phone, lp.user_id, lu.name, dict.dict_type FROM lw_phone lp LEFT JOIN lw_user lu ON lp.user_id = lu.id LEFT JOIN t_dict_ex dict ON dict.id = lp.phone limit 10
2024-10-22 18:37:59.213 INFO 44048 - ShardingSphere-SQL : Actual SQL: master ::: SELECT lp.id, lp.phone, lp.user_id, lu.name, dict.dict_type FROM lw_phone lp LEFT JOIN lw_user lu ON lp.user_id = lu.id LEFT JOIN t_dict_ex dict ON dict.id = lp.phone limit 10
FROM `logic_db`.`lw_phone`
2024-10-22 18:37:59.245 INFO 44048 - ShardingSphere-SQL : SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
FROM `lw_phone`
FROM `logic_db`.`lw_user`
2024-10-22 18:38:02.606 INFO 44048 - ShardingSphere-SQL : SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
FROM `lw_user`
FROM `logic_db`.`t_dict_ex`
2024-10-22 18:38:02.733 INFO 44048 - ShardingSphere-SQL : SQLStatement: MySQLSelectStatement(table=Optional.empty, limit=Optional.empty, lock=Optional.empty, window=Optional.empty)
FROM `t_dict_ex`
方案总结
ShardingSphere 整体使用成本较低,但最终没有采用 ShardingSphere 联邦查询,主要考虑了两点:
1、联邦查询性能较低:
经过针对实际业务的多种场景进行测试,联邦查询性能比同库查询的性能慢了非常多,虽然这种耗时是可以理解的,毕竟类似应用层聚合计算,不过以实际业务场景来说,这种耗时是无法接受的。
2、数据库兼容性问题:
如果产品需求是要兼容多种主流数据库,包括国产数据库、Oracle,那 ShardingSphere 可能并不是一种很好的方案,这里主要只联邦查询功能,其他功能没有深入使用,不敢断言。关于联邦查询,官网也表示该功能还在实验当中。
踩坑说明
截止文章编写阶段,ShardingSphere 的最新版是5.5.1
,而网上很多教程的版本较低,不同版本的JDBC模式的配置和操作存在若干差异,尤其是联邦查询
这类新功能,官网缺少详细说明,使用时注意鉴别。
总结陈词
本篇文章大体介绍了ShardingSphere-JDBC实现联邦查询,由于篇幅所限,仅展示简单示例分析。
💗 后续也会逐步分享企业实际开发中的实战经验,有需要交流的可以联系博主。