首页 > 其他分享 >ShardingSphere之ShardingProxy实战操作、分布式事务

ShardingSphere之ShardingProxy实战操作、分布式事务

时间:2024-08-07 21:27:34浏览次数:18  
标签:事务 -- ShardingSphere XA ShardingProxy proxy 分布式

文章目录



简介

ShardingSphere的两个核心产品分别为ShardingJDBC和ShardingProxy。前文已经详细介绍了ShardingJDBC的具体使用,接下来介绍服务端的分库分表ShardingProxy。

定位为一个透明化的数据库代理,目前提供MySQL和PostgreSQL协议,透明化数据库操作。简单理解就是,他会部署成一个MySQL或者PostgreSQL的数据库服务,应用程序只需要像操作单个数据库一样去访问ShardingSphere-proxy,由ShardingProxy去完成分库分表功能。

在这里插入图片描述



ShardingProxy的主要功能如下:

  • 配合 ORM 框架使用更友好

    当使用 ShardingSphere-JDBC 时,需要在代码中直接编写分库分表的逻辑,如果使用 ORM 框架,会产生冲突。ShardingSphere-Proxy 作为服务端中间件,可以无缝对接 ORM 框架。

  • 对 DBA 更加友好

    ShardingSphere-Proxy 作为服务端代理,对 DBA 完全透明。DBA 可以直接操作原始数据源,而不需要了解 ShardingSphere 的功能和 API。这简化了 DBA 的工作,也不会产生额外学习成本。

  • 避免在项目中侵入分库分表逻辑

    使用 ShardingSphere-JDBC,需要在业务代码中编写分库分表规则配置,这会使代码显得繁琐,且一旦规则变更,需要修改大量代码。ShardingSphere-Proxy 通过外部配置实现规则管理,可以避免这种情况。

  • 提供分布式事务支持

    ShardingSphere-Proxy 可以与第三方事务管理器对接,提供对分布式数据库的分布式事务支持。而 ShardingSphere-JDBC 仅支持本地事务。

  • 实现无中心化数据治理

    通过 ShardingSphere-Proxy,可以将多个数据源注册到同一个代理服务中,实现跨数据源的数据治理、监控和报警等功能。这有利于大规模微服务系统的运维。



基础使用

部署ShardingProxy

ShardingProxy 5.2.1版本下载

直接下载地址

ShardingProxy在windows和Linux上提供了一套统一的部署发布包。下载apache-shardingsphere-5.2.1-shardingsphere-proxy-bin.tar.gz文件后,直接进行解压



解压完成后,我们需要把MySQL的JDBC驱动包mysql-connector-java-8.0.15.jar手动复制到%SHARDINGSPHERE_PROXY_HOME%/ext-lib目录下,ext-lib目录需要我们自己创建,所有扩展的jar包都丢在这里面。ShardingProxy默认只附带了PostgreSQL的JDBC驱动包,而不包含MySQL的JDBC驱动包。

在这里插入图片描述



接下来进入conf目录,进行相关的配置,常见的几个配置文件如下所示

每个配置文件里都给出了配置的示例,照着改改就行。再加上我们学习过ShardingJDBC,所以基本上是无门槛看懂这些配资

在这里插入图片描述



先打开server.yaml,更改其中的配置

mode:
  type: standalone    # 我这里先以单机启动
#  type: Cluster
#  repository:
#    type: ZooKeeper
#    props:
#      namespace: governance_ds
#      server-lists: localhost:2181
#      retryIntervalMilliseconds: 500
#      timeToLiveSeconds: 60
#      maxRetries: 3
#      operationTimeoutMilliseconds: 500

rules:
  - !AUTHORITY
    users:				# 连接用户名密码
      - root@%:root
      - sharding@:sharding
    provider:				# 权限
      type: ALL_PERMITTED
  - !TRANSACTION			# 分布式事务
    defaultType: XA
    providerType: Atomikos
  - !SQL_PARSER
    sqlCommentParseEnabled: true
    sqlStatementCache:
      initialCapacity: 2000
      maximumSize: 65535
    parseTreeCache:
      initialCapacity: 128
      maximumSize: 1024

props:
  max-connections-size-per-query: 1
  kernel-executor-size: 16  # Infinite by default.
  proxy-frontend-flush-threshold: 128  # The default value is 128.
  proxy-hint-enabled: false		# 是否允许hint
  sql-show: false			# 是否打印日志
  check-table-metadata-enabled: false
    # Proxy backend query fetch size. A larger value may increase the memory usage of ShardingSphere Proxy.
    # The default value is -1, which means set the minimum value for different JDBC drivers.
  proxy-backend-query-fetch-size: -1
  proxy-frontend-executor-size: 0 # Proxy frontend executor size. The default value is 0, which means let Netty decide.
    # Available options of proxy backend executor suitable: OLAP(default), OLTP. The OLTP option may reduce time cost of writing packets to client, but it may increase the latency of SQL execution
    # and block other clients if client connections are more than `proxy-frontend-executor-size`, especially executing slow SQL.
  proxy-backend-executor-suitable: OLAP
  proxy-frontend-max-connections: 0 # Less than or equal to 0 means no limitation.
    # Available sql federation type: NONE (default), ORIGINAL, ADVANCED
  sql-federation-type: NONE
    # Available proxy backend driver type: JDBC (default), ExperimentalVertx
  proxy-backend-driver-type: JDBC
  proxy-mysql-default-version: 8.0.15 # 修改成我们自己的版本
  proxy-default-port: 3307 # 连接端口
  proxy-netty-backlog: 1024 # Proxy netty backlog.



  • mode部分的配置就是ShardingProxy的启动方式,默认是集群方式启动的,配置中心使用的是zookeeper,我们也可以先暂时改为单机启动

  • rules

    • AUTHORITY部分就是登录用户名密码以及权限,前文就介绍过ShardingProxy是一个数据库代代理,我们可以把它当成一个数据库,这里就是该数据库的登录用户
    • TRANSACTION部分分布式事务控制器,下文会详细介绍
  • props部分配置服务端的一些参数

    • max-connections-size-per-query参数是对于ShardingProxy最重要的优化参数,表示一个数据库连接对象最大执行的sql数。在上一章节介绍ShardingSphere的执行引擎以及结果归并时介绍到了,

      如果只需要一个数据库连接就能完成相关操作就是内存限制模式,结果归并时是流式分组归并,查询相对慢,结果归并效率相对高;如果需要多个数据库连接才能完成相关操作就是连接限制模式,结果归并时是内存分组归并,因为多个连接同时查询所以查询相对快,结果归并效率相对慢。

      举例:通过sql解析我知道了一次业务请求需要执行5条sql,但是我max-connections-size-per-query参数设置了1就表示一个连接对象只能执行一条sql,那么就需要5个连接对象,如果max-connections-size-per-query参数设置了5,就表示我只需要一个连接对象

    • proxy-mysql-default-version表示ShardingProxy所模拟的MySQL服务版本。为了与之前的示例兼容,我们这里可以将它改成8.0.15版本。

    • proxy-default-port表示模拟的MySQL服务的端口。 最好和本机mysql真实启动端口区分开,避免端口冲突



接下来运行bin/start.bat进行启动

在这里插入图片描述



进行连接测试

在这里插入图片描述



配置分库分表策略

我们此时连接,发下会报错,因为我们还没有配置相关的分库分表路由策略

在这里插入图片描述



接下来操作conf/config-sharding.yaml文件,该文件中上方是postgresql配置,下方是mysql配置。具体的配置内容就和ShardingJDBC一样,具体配置如下

# 指定数据库名,也就是连接ShardingProxy时 使用的是哪一个数据库
databaseName: sharding_hs_db

dataSources:
  ds_0:
    url: jdbc:mysql://localhost:3306/sharding_sphere1?serverTimezone=UTC&useSSL=false
    username: root
    password: 1234
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1
  ds_1:
    url: jdbc:mysql://localhost:3306/sharding_sphere2?serverTimezone=UTC&useSSL=false
    username: root
    password: 1234
    connectionTimeoutMilliseconds: 30000
    idleTimeoutMilliseconds: 60000
    maxLifetimeMilliseconds: 1800000
    maxPoolSize: 50
    minPoolSize: 1

rules:
- !SHARDING
  tables:
    # 逻辑表
    sys_user:
      actualDataNodes: ds_${0..1}.sys_user${1..2}
      # 分表策略
      tableStrategy:
        standard:
          shardingColumn: uid
          shardingAlgorithmName: sys_user_tab_alg
      # 分布式主键生成策略
      keyGenerateStrategy:
        column: uid
        keyGeneratorName: alg_snowflake


  # 默认分库策略
  defaultDatabaseStrategy:
    standard:
      shardingColumn: uid
      shardingAlgorithmName: database_inline
  # 默认分表策略
  defaultTableStrategy:
    none:

  # 分片策略
  shardingAlgorithms:
    database_inline:
      type: INLINE
      props:
        algorithm-expression: ds_${uid % 2}
    sys_user_tab_alg:
      type: INLINE
      props:
        algorithm-expression: sys_user$->{((uid+1)%4).intdiv(2)+1}
  
  # 分布式主键生成策略
  keyGenerators:
    alg_snowflake:
      type: COSID_SNOWFLAKE



接下来再重启ShardingProxy服务,在进行连接

在这里插入图片描述



多数据库,出现为分片数据表同名情况

这里有一个小问题,如下图所示,我两个真实数据库中都存在user_info1 user_info2数据表,我没有在ShardingProxy中配置user_info数据表相关的分片规则,此时只有一个sys_user表的分片规则,在ShardingProxy中保存是user_info1 user_info2数据表的内容只有下面两个数据库的其中一个数据库中的内容。

在这里插入图片描述



真实库中,存在真实表和分片逻辑表同名情况

直接访问ShardingProxy的sys_user逻辑表,只会查询到对应分片路由规则真实表数据,而不会存在下方uid=1026的数据

在这里插入图片描述



分布式事务机制

介绍

开发者手册

用户手册

在ShardingProxy的conf/server.yaml配置文件中,有以下的默认配置项

在这里插入图片描述



ShardingProxy默认是使用的XA方式来保证的分布式事务,而且默认使用的是Atomikos框架。

我们从开发者手册可以得知,目前它支持三种XA分布式事务管理器



全限定类名:org.apache.shardingsphere.transaction.xa.spi.XATransactionManagerProvider

XA 分布式事务管理器,已知实现

配置标识详细说明类名
Atomikos基于 Atomikos 的 XA 分布式事务管理器AtomikosTransactionManagerProvider
Narayana基于 Narayana 的 XA 分布式事务管理器NarayanaXATransactionManagerProvider
Bitronix基于 Bitronix 的 XA 分布式事务管理器BitronixXATransactionManagerProvider



XA事务Demo

引入Maven依赖

<!--XA 分布式事务 -->
<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-transaction-xa-core</artifactId>
    <version>5.2.1</version>
    <exclusions>
        <exclusion>
            <artifactId>transactions-jdbc</artifactId>
            <groupId>com.atomikos</groupId>
        </exclusion>
        <exclusion>
            <artifactId>transactions-jta</artifactId>
            <groupId>com.atomikos</groupId>
        </exclusion>
    </exclusions>
</dependency>
<!-- 版本滞后了 -->
<dependency>
    <artifactId>transactions-jdbc</artifactId>
    <groupId>com.atomikos</groupId>
    <version>5.0.8</version>
</dependency>
<dependency>
    <artifactId>transactions-jta</artifactId>
    <groupId>com.atomikos</groupId>
    <version>5.0.8</version>
</dependency>

<!-- 使用XA事务时,可以引入其他几种事务管理器 -->
<!--        <dependency>-->
<!--            <groupId>org.apache.shardingsphere</groupId>-->
<!--            <artifactId>shardingsphere-transaction-xa-bitronix</artifactId>-->
<!--            <version>5.2.1</version>-->
<!--        </dependency>-->
<!--        <dependency>-->
<!--            <groupId>org.apache.shardingsphere</groupId>-->
<!--            <artifactId>shardingsphere-transaction-xa-narayana</artifactId>-->
<!--            <version>5.2.1</version>-->
<!--        </dependency>-->



配置事务管理器

@Configuration
@EnableTransactionManagement
public class TransactionConfiguration {
    
    @Bean
    public PlatformTransactionManager txManager(final DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}



然后就可以写一个示例

public class MySQLXAConnectionTest {
    public static void main(String[] args) throws SQLException {
        //true表示打印XA语句,,用于调试
        boolean logXaCommands = true;
        // 获得资源管理器操作接口实例 RM1
        Connection conn1 = DriverManager.getConnection("jdbc:mysql://localhost:3306/coursedb?serverTimezone=UTC", "root", "root");
        XAConnection xaConn1 = new MysqlXAConnection((com.mysql.cj.jdbc.JdbcConnection) conn1, logXaCommands);
        XAResource rm1 = xaConn1.getXAResource();
        
        // 获得资源管理器操作接口实例 RM2
        Connection conn2 = DriverManager.getConnection("jdbc:mysql://localhost:3306/coursedb2?serverTimezone=UTC", "root", "root");
        XAConnection xaConn2 = new MysqlXAConnection((com.mysql.cj.jdbc.JdbcConnection) conn2, logXaCommands);
        XAResource rm2 = xaConn2.getXAResource();
        
        // AP请求TM执行一个分布式事务,TM生成全局事务id
        byte[] gtrid = "g12345".getBytes();
        int formatId = 1;
        try {
            // ==============分别执行RM1和RM2上的事务分支====================
            // TM生成rm1上的事务分支id
            byte[] bqual1 = "b00001".getBytes();
            Xid xid1 = new MysqlXid(gtrid, bqual1, formatId);
            // 执行rm1上的事务分支
            rm1.start(xid1, XAResource.TMNOFLAGS);//One of TMNOFLAGS, TMJOIN, or TMRESUME.
            PreparedStatement ps1 = conn1.prepareStatement("INSERT INTO `dict` VALUES (1, 'T', '测试1');");
            ps1.execute();
            rm1.end(xid1, XAResource.TMSUCCESS);
            
            // TM生成rm2上的事务分支id
            byte[] bqual2 = "b00002".getBytes();
            Xid xid2 = new MysqlXid(gtrid, bqual2, formatId);
            // 执行rm2上的事务分支
            rm2.start(xid2, XAResource.TMNOFLAGS);
            PreparedStatement ps2 = conn2.prepareStatement("INSERT INTO `dict` VALUES (2, 'F', '测试2');");
            ps2.execute();
            rm2.end(xid2, XAResource.TMSUCCESS);
            
            // ===================两阶段提交================================
            // phase1:询问所有的RM 准备提交事务分支
            int rm1_prepare = rm1.prepare(xid1);
            int rm2_prepare = rm2.prepare(xid2);
            // phase2:提交所有事务分支
            boolean onePhase = false; //TM判断有2个事务分支,所以不能优化为一阶段提交
            if (rm1_prepare == XAResource.XA_OK
                    && rm2_prepare == XAResource.XA_OK
            ) {//所有事务分支都prepare成功,提交所有事务分支
                rm1.commit(xid1, onePhase);
                rm2.commit(xid2, onePhase);
            } else {//如果有事务分支没有成功,则回滚
                rm1.rollback(xid1);
                rm1.rollback(xid2);
            }
        } catch (XAException e) {
            // 如果出现异常,也要进行回滚
            e.printStackTrace();
        }
    }
}



这其中,XA标准规范了事务XID的格式。有三个部分: gtrid [, bqual [, formatID ]] 其中

  • gtrid 是一个全局事务标识符 global transaction identifier
  • bqual 是一个分支限定符 branch qualifier 。如果没有提供,会使用默认值就是一个空字符串。
  • formatID 是一个数字,用于标记gtrid和bqual值的格式,这是一个正整数,最小为0,默认值就是1。



但是使用XA事务时需要注意以下几点:

  • XA事务无法自动提交
  • XA事务效率非常低下,全局事务的状态都需要持久化。性能非常低下,通常耗时能达到本地事务的10倍。
  • XA事务在提交前出现故障的话,很难将问题隔离开。



使用另外两种XA事务管理器

我们从开发者手册可以得知,在ShardingProxy5.2.1版本中它支持三种XA分布式事务管理器。如果不想使用默认的Atomikos,而去使用Narayana,具体的操作如下所示:

全限定类名:org.apache.shardingsphere.transaction.xa.spi.XATransactionManagerProvider

XA 分布式事务管理器,已知实现

配置标识详细说明类名
Atomikos基于 Atomikos 的 XA 分布式事务管理器AtomikosTransactionManagerProvider
Narayana基于 Narayana 的 XA 分布式事务管理器NarayanaXATransactionManagerProvider
Bitronix基于 Bitronix 的 XA 分布式事务管理器BitronixXATransactionManagerProvider



我们微服务项目中,默认情况下都是没有这个包的

<dependency>
    <groupId>org.apache.shardingsphere</groupId>
    <artifactId>shardingsphere-jdbc-core-spring-boot-starter</artifactId>
    <version>5.2.1</version>
</dependency>

在这里插入图片描述



我们可以通过下载ShardingProxy的源码包,从源码包中找上上方对应的NarayanaXATransactionManagerProvider,然后查看这个类所在是pom文件,最终找到pom依赖

<!--        <dependency>-->
<!--            <groupId>org.apache.shardingsphere</groupId>-->
<!--            <artifactId>shardingsphere-transaction-xa-bitronix</artifactId>-->
<!--            <version>5.2.1</version>-->
<!--        </dependency>-->
<!--        <dependency>-->
<!--            <groupId>org.apache.shardingsphere</groupId>-->
<!--            <artifactId>shardingsphere-transaction-xa-narayana</artifactId>-->
<!--            <version>5.2.1</version>-->
<!--        </dependency>-->

我们在微服务中导入上面对应的依赖,再从本地maven仓库中拿到对应的jar包,丢到%SHARDINGSPHERE_PROXY_HOME%/ext-lib目录下



在server.yaml中就可以将事务的Provider配置成Narayana

下面这个Narayana字符串是通过源码NarayanaXATransactionManagerProvider类的getType()方法中定义的

rules:
  - !TRANSACTION
    defaultType: XA
    providerType: Narayana

标签:事务,--,ShardingSphere,XA,ShardingProxy,proxy,分布式
From: https://blog.csdn.net/qq_44027353/article/details/140927178

相关文章

  • ShardingSphere之ShardingProxy集群部署
    文章目录介绍使用Zookeeper进行集群部署统一ShardingJDBC和ShardingProxy配置通过Zookeeper注册中心同步配置直接使用ShardingProxy提供的JDBC驱动读取配置文件介绍开发者手册在conf/server.yaml配置文件中有下面这一段配置,就是关于集群部署的mode:#type:stan......
  • ceph分布式存储系统
    cephceph是一个开源的,用c++语言编写的分布式的存储系统,存储文件数据。lvm逻辑卷可以扩容raid磁盘阵列高可用基于物理意义上的存储系统分布式就是多台物理磁盘组成的一个集群,在这个基础之后实现高可用,扩展特点:1、远程访问2、多个服务器组成的虚拟硬盘3、分布式......
  • 一文速通Redis常见问题,带你深入了解Redis数据结构、分布式锁、持久化策略等经典问题。
    本文参考资料:黑马Redis讲义本文参考资料:JavaGuide,guide哥的八股内容个人思考的Redis实践,面试问题的总结,反思目录Redis五大数据结构String1.String数据结构(SDS)2.String应用场景3.Hash与String存储对象的区别SetListHashSortedSetRedis三种特殊数据结构BitMap(位图)......
  • 高并发下的分布式缓存 | 缓存系统稳定性设计
    缓存击穿(CacheBreakdown)缓存击穿是指一个热点数据在缓存中失效后,可能同一时刻会有很多对该热点数据的请求,这些请求都无法在缓存中找到该数据,因此都会访问数据库,导致数据库压力骤增。解决缓存击穿的主流方案有两种:互斥锁异步刷新热点缓存互斥锁在缓存失效时,使用互斥锁(......
  • 高并发下的分布式缓存 | Cache-Aside缓存模式
    Cache-aside模式的缓存操作Cache-aside模式,也叫旁路缓存模式,是一种常见的缓存使用方式。在这个模式下,应用程序可能同时需要同缓存和数据库进行数据交互,而缓存和数据库之间是没有直接联系的。这意味着,应用程序代码要负责处理数据的获取和存储,一些应用程序使用“Read-Thr......
  • 部署伪分布式 Hadoop集群
    部署伪分布式Hadoop集群一、JDK安装配置1.1下载JDK1.2上传解压1.3java环境配置二、伪分布式Hadoop安装配置2.1Hadoop下载2.2上传解压2.3Hadoop文件目录介绍2.4Hadoop配置2.4.1修改core-site.xml配置文件2.4.2修改hdfs-site.xml配置文件2.4.3修改ha......
  • 基于simulink的分布式发电系统自动重合闸的建模与仿真分析
    1.课题概述      在配电系统中,80%-90%的故障都是瞬时故障。发生故障时,线路被保护迅速断开,随即重合闸。当分布式电源接入配电网后,线路发生故障后重合闸,此时分布式电源没有跳离线路,这将产生两种潜在威胁,即非同期重合闸和故障点电弧重燃。      非同期重合闸:当线路......
  • 新手小白的Hadoop分布式和集群简述
    Hadoop分布式简介:ApacheHadoop是一个开源的分布式计算框架,它允许用户在节点组成的集群中处理和分析大数据。Hadoop是“Hadoop之父”DougCutting的著作,最初是在Nutch搜索引擎项目中开发的,用于解决网页爬虫的存储和搜索问题。Hadoop的核心由以下几个部分组成:HDFS(Hadoop......
  • 分布式存储MinIO Console
    MinIO是什么?一种对象存储解决方案,Minio提供与亚马逊云科技S3兼容的API,并支持所有核心S3功能,所以也可以看做是S3的开源版本;它允许用户通过简单的API接口进行数据的存储和检索,同时提供高度可扩展性和强大的数据保护机制。MinIo主要是在微服务系统中使用,非常适合于存储......
  • 分布式主键 详解
    文章目录雪花算法结合分库分表的问题问题出现原因分析解决思路分布式主键要考虑的问题主键生成策略雪花算法详解时间戳位问题工作进程位问题序列号位问题根据雪花算法扩展基因分片法雪花算法结合分库分表的问题问题出现使用ShardingSphere框架自带的雪花算法生成......