《ShardingSphere 联邦查询分析》

📢 大家好,我是 【战神刘玉栋】,有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实现联邦查询,由于篇幅所限,仅展示简单示例分析。

💗 后续也会逐步分享企业实际开发中的实战经验,有需要交流的可以联系博主。

相关推荐
wuweijie@apache.org3 个月前
IntelliJ IDEA 集成 ShardingSphere-JDBC 访问分库分表
ide·intellij-idea·shardingsphere·分库分表
Hello-Brand4 个月前
数据库系列: 主流分库分表中间件介绍(图文总结)
mysql·shardingsphere·分库分表·mycat·数据库中间件·vitess
xiaomifeng10107 个月前
Apache ShardingSphere知识点表格总结及配置示例
数据库·事务·shardingsphere·读写分离·分布式事务·分表分库
星辰_mya7 个月前
ShardingSphere再回首
大数据·sql·mysql·database·shardingsphere
my_styles8 个月前
sharding‐jdbc之分库分表实战
数据库·shardingsphere·分库分表·sharding-jdbc
FlyingZCC8 个月前
ShardingSphere-SQL 解析 Issue 处理流程
shardingsphere·sql解析·antlr
緈諨の約錠9 个月前
基于smilehappiness-framework-base,快速集成ShardingSphere JDBC
java·shardingsphere·分库分表
青花锁10 个月前
Java微服务系列之 ShardingSphere - ShardingSphere-JDBC
java·开发语言·微服务·shardingsphere·分库分表
way_more1 年前
Spring Boot整合Sharding-JDBC实现强制路由
java·数据库·spring boot·后端·shardingsphere