• Sharding-JDBC概述


    一、Sharding-JDBC概述

    1.概念及主要功能

    • 随着通信技术的革新,全新领域的应用层出不穷,数据存量随着应用的探索不断增加,数据的存储和计算模式无时无刻不面临着创新。面对交易、大数据、关联分析、物联网等场景越来越细分,单一数据库再也无法适用于所有的应用场景。于此同时,场景内部也愈加细化,相似场景使用不同数据库已成为常态。由此可见,数据库碎片化的趋势已经不可逆转。
    • Sharding-JDBC是Apache ShardingSphere生态圈中一款开源的分布式数据库第三方组件。ShardingSphere由Sharding-JDBC、Sharding-Proxy和Sharding-Sidecar(规划中)这三款相互独立的产品组成。它们均提供标准化的数据分片、分布式事务和数据库治理功能,适用于Java同构、异构语言、容器、云原生等各种多样化的应用场景。
      Sharding-JDBC定位为轻量级Java框架,在Java的JDBC层提供额外的服务。它使用客户端直连数据库,以jar包形式提供服务,无需额外部署和依赖,可理解为增强版的JDBC驱动,完全兼容JDBC和各种ORM框架的使用。
    • 适用于任何基于Java的ORM框架,如JPA、Hibernate、Mybatis、Spring JDBC Template或者直接使用JDBC。
      基于任何第三方数据库连接池,如DBCP、C3P0、BoneCP、Druid、HikariCP等。
      支持任意实现JDBC规范的数据库,目前支持MySQL、Oracle、SQLServer和PostgreSQL。

    主要功能

    1. 数据分片
      • 分库
      • 分表
      • 读写分离
      • 分片策略
      • 分布式主键
    2. 分布式事务
      • 标准化的事务接口
      • XA强一致性事务
      • 柔性事务
    3. 数据库治理
      • 配置动态化
      • 编排和治理
      • 数据脱敏
      • 可视化链路追踪

    2.内部结构

    • 这部分表示的是Sharding-JDBC的入口API,采用工厂方法的形式提供。
      ShardingDataSourceFactory支持分库分表、读写分离操作。
      MasterSlaveDataSoureceFactory支持读写分离操作。

    • 这部分表示的是Sharding-JDBC的配置对象,提供灵活多变的配置方式。
      TableRuleConfiguration,它包含分片配置规则。
      MasterSlaveRuleConfiguration,它包含的是读写分离的配置规则
      ShardingRuleConfiguration,主入口,它包含多个TableRuleConfiguration,也可以包含多个MasterSlaveRuleConfiguration

    • 这部分表示的是内部对象,由Sharding-JDBC内部使用,应用开发者无需关注。
      Sharding-JDBC通过ShardingRuleConfiguration和MasterSlaveRuleConfiguration生成真正的规则对象,最终生成要使用的DataSource。

    • Sharding-JDBC初始化流程,根据配置信息生成configuration对象,通过Factory将configuration对象转化为Rule对象,通过Factory将Rule对象与DataSource对象进行封装,使用Sharding-JDBC进行分库分表操作。

    Sharding-JDBC的使用

    1. 引入maven依赖

       <!-- https://mvnrepository.com/artifact/org.apache.shardingsphere/sharding-jdbc-core -->
      
          org.apache.shardingsphere</groupId>
          sharding-jdbc-core</artifactId>
          4.1.1</version>
      </dependency>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
    2. 规则配置
      Sharding-JDBC可以通过Java、YAML、Spring命名空间和Spring Boot Starter四种方式配置,开发者根据场景选择合适的配置方式。

    3. 创建DataSource
      通过ShardingDataSourceFactory工厂和规则配置对象获取ShardingDataSource,然后即可通过DataSource选择使用原生JDBC开发,或者使用JPA,Mybatis等ORM工具。

    3.分片核心概念

    • 真实表:数据库中真实存在的物理表。例如b_order0、b_order1。

    • 逻辑表:在分片之后,同一类表结构的名称(总称)。例如b_order。

    • 数据节点:在分片之后,由数据源和数据表组成。例如ds0.b_order1。

    • 绑定表:指的是分片规则一致的关系表(主表、子表),例如b_order和b_order_item,均按照order_id分片,则此两个表互为绑定表关系。绑定表之间的多表关联查询不会出现笛卡尔积关联,可以提高关联查询的效率。
      例如:
      如果没有配置绑定关系,则采用笛卡尔积关联查询4条SQL语句,如下

      select * from b_order0 o left join b_order_item0 i on o.order_id = i.order_id where o.order_id in(10,11)
      select * from b_order0 o left join b_order_item1 i on o.order_id = i.order_id where o.order_id in(10,11)
      select * from b_order1 o left join b_order_item0 i on o.order_id = i.order_id where o.order_id in(10,11)
      select * from b_order1 o left join b_order_item1 i on o.order_id = i.order_id where o.order_id in(10,11)
      
      • 1
      • 2
      • 3
      • 4

      配置绑定,如下

      b_order:b_order0,b_order1
      b_order_item: b_order_item0,b_order_item1
      
      • 1
      • 2

      配置绑定关系后,只需查询2条SQL语句

      select * from b_order0 o left join b_order_item0 i on o.order_id = i.order_id where o.order_id in(10,11)
      select * from b_order1 o left join b_order_item1 i on o.order_id = i.order_id where o.order_id in(10,11)
      
      • 1
      • 2
    • 广播表,在使用中,有些表没必要做分片,例如字典表、省份信息等,因为他们数据量不大,而且这种表可能需要与海量数据的表进行关联查询。广播表会在不同的数据节点上进行存储,存储的表结构和数据完全相同。
      相当于MyCat的全局表。

    4. 分片流程解析

    1. SQL解析分为词法解析和语法解析。先通过词法解析器将SQL拆分为一个个不可再分的单词。再使用语法解析器对SQL进行理解,并最终提炼出解析上下文。Sharding-JDBC采用不同的解析器对SQL进行解析,解析器类型如下:
      MySQL解析器,Oracle解析器,SQLServer解析器,PsotgreSQL解析器,默认解析器 sql-92标准
    2. 查询优化,负责合并和优化分片条件,如OR等。
    3. SQL路由,根据解析上下文匹配用户配置的分片策略,并生成路由路径。目前支持分片路由和广播路由。
    4. SQL改写,将SQL改写为在真实数据库中可以正确执行的语句。SQL改写分为正确性改写和优化改写。
    5. SQL执行,通过多线程执行器异步执行SQL。
    6. 结果归并,将多个执行结果集归并以便于通过统一的JDBC接口输出。结果归并包括流失归并、内存归并和使用装饰者模式的追加归并这几种方式。

    5.SQL规范

    • SQL使用规范,兼容全部常用的路由至但数据节点的SQL;路由至多数据节点的SQL由于场景复杂,分为稳定支持、实验性支持和不支持这三种情况。
    1. 稳定支持
      全面支持DQL、DML、DDL、DCL、TCL和常用的DAL。支持分页、去重、排序、分组、聚合、表关联等复杂查询。

      • 常规查询
        • SELECT 主语句

          SELECT select_expr [, select_expr ...] FROM table_reference [, table_reference ...]
          [WHERE predicates]
          [GROUP BY {col_name | position} [ASC | DESC], ...]
          [ORDER BY {col_name | position} [ASC | DESC], ...]
          [LIMIT {[offset,] row_count | row_count OFFSET offset}]
          
          • 1
          • 2
          • 3
          • 4
          • 5
        • select_expr

          * | 
          [DISTINCT] COLUMN_NAME [AS] [alias] | 
          (MAX | MIN | SUM | AVG)(COLUMN_NAME | alias) [AS] [alias] | 
          COUNT(* | COLUMN_NAME | alias) [AS] [alias]
          
          • 1
          • 2
          • 3
          • 4
        • table_reference

          tbl_name [AS] alias] [index_hint_list]
          | table_reference ([INNER] | {LEFT|RIGHT} [OUTER]) JOIN table_factor [JOIN ON conditional_expr | USING (column_list)]
          
          • 1
          • 2
      • 子查询
        子查询和外层查询同时指定分片键,且分片键的值保持一致时,由内核提供稳定支持。
        SELECT * FROM (SELECT * FROM t_order WHERE order_id = 1) o WHERE o.order_id = 1;
        
        • 1
    2. 实验性支持
      实验性支持,特指使用Federation执行引擎提供支持。该引擎处于快速开发中,用户虽基本可用,但仍需大量优化,是实验性产品。

      • 子查询
        子查询和外层查询未同时指定分片键,或分片键的值不一致时,由Federation执行引擎提供支持。

      • 跨库关联查询
        当关联查询中的多个表分布在不同的数据库实例上时,由Federation执行引擎提供支持。假设t_order和t_order_item是多数据节点的分片表,并且未配置绑定表规则,t_user和t_user_role是分布在不同的数据库实例上的单表,那么Federation执行引擎能够支持如下的关联查询。

        SELECT * FROM t_order o INNER JOIN t_order_item i ON o.order_id = i.order_id WHERE o.order_id = 1;
        SELECT * FROM t_order o INNER JOIN t_user u ON o.user_id = u.user_id WHERE o.user_id = 1;
        SELECT * FROM t_order o LEFT JOIN t_user_role r ON o.user_id = r.user_id WHERE o.user_id = 1;
        SELECT * FROM t_order_item i LEFT JOIN t_user u ON i.user_id = u.user_id WHERE i.user_id = 1;
        SELECT * FROM t_order_item i RIGHT JOIN t_user_role r ON i.user_id = r.user_id WHERE i.user_id = 1;
        SELECT * FROM t_user u RIGHT JOIN t_user_role r ON u.user_id = r.user_id WHERE u.user_id = 1;
        
        • 1
        • 2
        • 3
        • 4
        • 5
        • 6
    3. 不支持
      不支持CASE WHEN 语句
      SELECT子句不支持*和内置分布式主键生成器。
      查询列式函数表达式时,查询列前不能使用表名,只能使用表别名。

    6.行表达式(Inline)

    Inline可以简化数据节点和分片算法配置信息,主要是解决实现配置简化、配置一体化。

    1. Inline表达式说明
      ${begin…end}表示范围区间, ${[unit1,unit2,unitx]}表示枚举值。inline表达式中连续多个 ${…}表达式,整个inline最终的结果将会根据每个子表达式的结果进行笛卡尔积组合,例如正式表inline表达式如下:

      dbtbl_${['online','offline']}_${1..3}
      dbtbl_$->{['online','offline']}_$->{1..3}
      
      • 1
      • 2

      最终会解析为dbtbl_online_1,dbtbl_online_2,dbtbl_online_3,dbtbl_offline_1,dbtbl_offline_2,dbtbl_offline_3 这6张表。

    2. 数据节点配置
      字符串中使用${}来嵌入groovy代码,下面的表达式中data_source_是字符串前缀,id%2+1是groovy代码。

      data_source_${id%2+1}
      
      • 1

      结果为data_source_1,data_source_2

    3. db0、db1,每个库下面都有order0,order1两张表,行表达式配置如下

      db${0..1}.order${0..1}
      
      • 1

      db0下面有order0、order1两张表,db1下面有order2、order3、order4四张表,配置如下

      db0.order${0..1},db1.order${2..4}
      
      • 1

    总结

    1. 使用Sharding-JDBC需要引入sharding-jdbc-core包。
      ShardingJDBC内部结构由三部分组成,即入口API、配置对象和内部对象。就是配置对象通过入口API传递进Sharding-JDBC,然后它会根据配置对象生成内部对象(即规则对象),然后用它来进行分库分表操作。
      分片流程,即SQL解析→查询优化→SQL路由→SQL改写→SQL执行→结果归并。
  • 相关阅读:
    [设计模式] 简单工厂模式简易案例
    评估APP网页小程序代码UI开发H5估价师怎么评估开发精确研发价格?
    2022.11.4 英语背诵
    Spring和SpringBoot学习
    常见的数码管中的引脚分布情况
    如何解决kafka rebalance导致的暂时性不能消费数据问题
    CCF ChinaSoft 2023 论坛巡礼|形式验证@EDA论坛
    java路线
    【前端笔记】小记一次Antd Vue 1.x (for vue2.x) icons组件按需引入的实现
    每日三题 7.24
  • 原文地址:https://blog.csdn.net/weixin_49076273/article/details/126762436