前言
提示:以下是本篇文章正文内容
一、ShardingSphere
官方使用手册链接: https://shardingsphere.apache.org/document/legacy/3.x/document/cn/features/sharding/concept/sql/.
示例:pandas 是基于NumPy 的一种工具,该工具是为了解决数据分析任务而创建的。
二、搭建步骤步骤
1.主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.qch.mysql</groupId>
<artifactId>mysql-example</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>sharding-jdbc-example</module>
</modules>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.compile.sourceEncoding>UTF-8</project.compile.sourceEncoding>
<springboot.version>2.2.5.RELEASE</springboot.version>
</properties>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
<version>${springboot.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.46</version>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
<version>4.1.0</version>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>8</source>
<target>8</target>
<testTarget>8</testTarget>
</configuration>
<version>3.8.1</version>
</plugin>
</plugins>
</build>
</project>
2.创建module:sharding-jdbc-example
1)分库
1、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">
<parent>
<artifactId>mysql-example</artifactId>
<groupId>com.qch.mysql</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>com.qch.mysql</groupId>
<artifactId>sharding-jdbc-example</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-jdbc-spring-boot-starter</artifactId>
</dependency>
</dependencies>
</project>
2、创建表对应pojo类
package com.qch.entity;
import javax.persistence.*;
import java.io.Serializable;
/**
* @Author qch
* @Date 2021/4/14
*/
@Entity
@Table(name="position")
public class Position implements Serializable {
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
@Column(name = "name")
private String name;
@Column(name = "salary")
private String salary;
@Column(name = "city")
private String city;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSalary() {
return salary;
}
public void setSalary(String salary) {
this.salary = salary;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
}
3、创建respository
public interface PositionRepository extends JpaRepository<Position,Long> {
@Query(nativeQuery = true,value = "select p.id,p.name,p.salary,p.city,pd.description from position p join position_detail pd on(p.id=pd.pid) where p.id=:id")
public Object findPositionsById(@Param("id") long id);
}
4.重要配置
1)、application.properties
#加载的时候就是application+sharding-database 文件
spring.profiles.active=sharding-database
#打印sql数据
spring.shardingsphere.props.sql.show=true
2)、application-sharding-database.properties
#一、定义数据源
spring.shardingsphere.datasource.names=ds0,ds1
#默认连接池
spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://192.168.142.128:3306/lagou1?serverTimezone=GMT%2B8&useSSL=false
spring.shardingsphere.datasource.ds0.username=root
spring.shardingsphere.datasource.ds0.password=root
spring.shardingsphere.datasource.ds1.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds1.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds1.jdbc-url=jdbc:mysql://192.168.142.129:3306/lagou2?serverTimezone=GMT%2B8&useSSL=false
spring.shardingsphere.datasource.ds1.username=root
spring.shardingsphere.datasource.ds1.password=root
#二、指定分库策略sharding
#行表达式,根据id拆分
spring.shardingsphere.sharding.tables.position.database-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.position.database-strategy.inline.algorithm-expression=ds$->{id % 2}
spring.shardingsphere.sharding.tables.position_detail.database-strategy.inline.sharding-column=pid
spring.shardingsphere.sharding.tables.position_detail.database-strategy.inline.algorithm-expression=ds$->{pid % 2}
#id
#指定主键id的名字
spring.shardingsphere.sharding.tables.position.key-generator.column=id
#spring.shardingsphere.sharding.tables.position.key-generator.type=SNOWFLAKE
spring.shardingsphere.sharding.tables.position.key-generator.type=LAGOUKEY
spring.shardingsphere.sharding.tables.position_detail.key-generator.column=id
spring.shardingsphere.sharding.tables.position_detail.key-generator.type=SNOWFLAKE
#spring.shardingsphere.sharding.tables.position_detail.key-generator.type=LAGOUKEY
数据库连接常见问题配置解决:javax.net.ssl.SSLException MESSAGE: closing inbound before receiving peer’s close_notify
解决方法
将设置useSSL为false
generator.xml 解决代码
connectionURL="jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&useSSL=false"
注意 :xml文件中&是被禁止的需要用到它的转义字符"&"
若不是xml格式 解决代码
connectionURL="jdbc:mysql://localhost:3306/test?serverTimezone=GMT%2B8&useSSL=false"
3)、分片使用主键
自定义主键
package com.qch.id;
import org.apache.shardingsphere.core.strategy.keygen.SnowflakeShardingKeyGenerator;
import org.apache.shardingsphere.spi.keygen.ShardingKeyGenerator;
import java.util.Properties;
/**
* @Author qch
* @Date 2021/4/14
* #org.apache.shardingsphere.spi.keygen.ShardingKeyGenerator
*/
public class MyLagouId implements ShardingKeyGenerator {
private SnowflakeShardingKeyGenerator snow=new SnowflakeShardingKeyGenerator();
@Override
public Comparable<?> generateKey() {
System.out.println("---执行自定义主键生产器");
return snow.generateKey();
}
@Override
public String getType() {
return "LAGOUKEY";
}
@Override
public Properties getProperties() {
return null;
}
@Override
public void setProperties(Properties properties) {
}
}
使用spi
内容如下
2)广播表
#广播表Broadcast
spring.shardingsphere.sharding.broadcast-tables=city
spring.shardingsphere.sharding.tables.city.key-generator.column=id
spring.shardingsphere.sharding.tables.city.key-generator.type=SNOWFLAKE
3)分库分表
#分表 根据commpanyid拆分库,根据id拆分表
spring.shardingsphere.sharding.tables.b_order.database-strategy.inline.sharding-column=company_id
spring.shardingsphere.sharding.tables.b_order.database-strategy.inline.algorithm-expression=ds$->{company_id % 2}
spring.shardingsphere.sharding.tables.b_order.table-strategy.inline.sharding-column=id
spring.shardingsphere.sharding.tables.b_order.table-strategy.inline.algorithm-expression=b_order${id % 2}
spring.shardingsphere.sharding.tables.b_order.actual-data-nodes=ds${0..1}.b_order${0..1}
spring.shardingsphere.sharding.tables.b_order.key-generator.column=id
spring.shardingsphere.sharding.tables.b_order.key-generator.type=SNOWFLAKE
三、Sharding-Jdbc功能扩展
1、读写分离
透明化读写分离所带来的影响,让使用方尽量像使用一个数据库一样使用主从数据库集群,是ShardingSphere读写分离模块的主要设计目标。
主库、从库、主从同步、负载均衡
核心功能
- 提供一主多从的读写分离配置。仅支持单主库,可以支持独立使用,也可以配合分库分表使
用 - 独立使用读写分离,支持SQL透传。不需要SQL改写流程
同一线程且同一数据库连接内,能保证数据一致性。如果有写入操作,后续的读操作均从主库读取。 - 基于Hint的强制主库路由。可以强制路由走主库查询实时数据,避免主从同步数据延迟。
不支持项
- 主库和从库的数据同步
- 主库和从库的数据同步延迟
- 主库双写或多写
- 跨主库和从库之间的事务的数据不一致。建议在主从架构中,事务中的读写均用主库操作。
该处使用的url网络请求的数据。
application-master-slave.properties配置
#一、定义数据源
spring.shardingsphere.datasource.names=master,slave0
#默认连接池
spring.shardingsphere.datasource.master.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.master.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.master.jdbc-url=jdbc:mysql://192.168.142.128:3306/lagou1?serverTimezone=GMT%2B8&useSSL=false
spring.shardingsphere.datasource.master.username=root
spring.shardingsphere.datasource.master.password=root
spring.shardingsphere.datasource.slave0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.slave0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.slave0.jdbc-url=jdbc:mysql://192.168.142.129:3306/lagou2?serverTimezone=GMT%2B8&useSSL=false
spring.shardingsphere.datasource.slave0.username=root
spring.shardingsphere.datasource.slave0.password=root
#master-slave
spring.shardingsphere.masterslave.name=datasource
spring.shardingsphere.masterslave.master-data-source-name=master
spring.shardingsphere.masterslave.slave-data-source-names=slave0
#负载方式
spring.shardingsphere.masterslave.load-balance-algorithm-type=ROUND_ROBIN
spring.shardingsphere.sharding.tables.city.key-generator.column=id
spring.shardingsphere.sharding.tables.city.key-generator.type=SNOWFLAKE
2、hint强制路由
在一些应用场景中,分片条件并不存在于SQL,而存在于外部业务逻辑。因此需要提供一种通过在外部
业务代码中指定路由配置的一种方式,在ShardingSphere中叫做Hint。如果使用Hint指定了强制分片
路由,那么SQL将会无视原有的分片逻辑,直接路由至指定的数据节点操作。
HintManager主要使用ThreadLocal管理分片键信息,进行hint强制路由。在代码中向HintManager添
加的配置信息只能在当前线程内有效。
Hint使用场景:
- 数据分片操作,如果分片键没有在SQL或数据表中,而是在业务逻辑代码中
- 读写分离操作,如果强制在主库进行某些数据操作
使用
1)、自定义Hint
package com.qch.hint;
import org.apache.shardingsphere.api.sharding.hint.HintShardingAlgorithm;
import org.apache.shardingsphere.api.sharding.hint.HintShardingValue;
import java.util.ArrayList;
import java.util.Collection;
/**
* @Author qch
* @Date 2021/4/15
*/
public class MyHintShardingAlgorithm implements HintShardingAlgorithm<Long> {
@Override
public Collection<String> doSharding(Collection<String> availabeTargetNames, HintShardingValue<Long> hintShardingValue) {
Collection<String>result=new ArrayList<>();
//availabeTargetNames对应ds0,ds1
for (String availabeTargetName : availabeTargetNames) {
//拿到分片键的值
for (Long value : hintShardingValue.getValues()) {
if (availabeTargetName.endsWith(String.valueOf(value%2)))
{
((ArrayList<String>) result).add(availabeTargetName);
}
}
}
return result;
}
}
2)、application-hint-database.properties
spring.shardingsphere.sharding.tables.city.database-strategy.hint.algorithm-class-name=com.qch.hint.MyHintShardingAlgorithm
3)、测试
@Test
public void query()
{
//构建Hint
HintManager hintManager=HintManager.getInstance();
hintManager.setDatabaseShardingValue(1L);//强制路由到ds${xx%2}
List<City> all = cityRepository.findAll();
all.forEach(city -> {
System.out.println(city.getId()+"省:"+city.getName()+"市:"+city.getProvince());
});
}
3、数据脱敏
数据脱敏模块属于ShardingSphere分布式治理这一核心功能下的子功能模块。
- 在更新操作时,它通过对用户输入的SQL进行解析,并依据用户提供的脱敏配置对SQL进行改写,从而实现对原文数据进行加密,并将密文数据存储到底层数据库。
- 在查询数据时,它又从数据库中取出密文数据,并对其解密,最终将解密后的原始数据返回给用
户。
Apache ShardingSphere自动化&透明化了数据脱敏过程,让用户无需关注数据脱敏的实现细节,像使用普通数据那样使用脱敏数据
1 、脱敏规则
脱敏配置主要分为四部分:数据源配置,加密器配置,脱敏表配置以及查询属性配置
2、加密策略解析
ShardingSphere提供了两种加密策略用于数据脱敏,该两种策略分别对应ShardingSphere的两种加解
密的接口,即Encryptor和QueryAssistedEncryptor。
- Encryptor
ShardingSphere针对这种类型的脱敏解决方案提供了两种具体实现类,分别是MD5(不可逆),AES(可逆),用户只需配置即可使用这两种内置的方案。 - QueryAssistedEncryptor
安全性更高,对相同的内容加密的结果也不一样,更有利于保护用户的信息,防止撞库成功。
它提供三种函数进行实现,分别是encrypt(), decrypt(), queryAssistedEncrypt()。在encrypt()阶段,用户通过设置某个变动种子,例如时间戳。针对原始数据+变动种子组合的内容进行加密,就
能保证即使原始数据相同,也因为有变动种子的存在,致使加密后的脱敏数据是不一样的。在decrypt()可依据之前规定的加密算法,利用种子数据进行解密。
queryAssistedEncrypt()用于生成辅助查询列,用于原始数据的查询过程-》没有实现提供,需要自己去实现
使用
1)application-encryptor.properties
#一、定义数据源
spring.shardingsphere.datasource.names=ds0
#默认连接池
spring.shardingsphere.datasource.ds0.type=com.zaxxer.hikari.HikariDataSource
spring.shardingsphere.datasource.ds0.driver-class-name=com.mysql.jdbc.Driver
spring.shardingsphere.datasource.ds0.jdbc-url=jdbc:mysql://192.168.142.128:3306/lagou1?serverTimezone=GMT%2B8&useSSL=false
spring.shardingsphere.datasource.ds0.username=root
spring.shardingsphere.datasource.ds0.password=root
#encrypt数据脱敏
spring.shardingsphere.encrypt.tables.c_user.columns.pwd.plain-column=pwd_plain
spring.shardingsphere.encrypt.tables.c_user.columns.pwd.cipher-column=pwd_cipher
spring.shardingsphere.encrypt.encryptors.qch_pwd.type=aes
spring.shardingsphere.encrypt.encryptors.qch_pwd.props.aes.key.value=1234
spring.shardingsphere.encrypt.tables.c_user.columns.pwd.encryptor=qch_pwd
#查询控制用铭文还是密文
spring.shardingsphere.props.query.with.cipher.column=true
#id
spring.shardingsphere.sharding.tables.c_user.key-generator.column=id
spring.shardingsphere.sharding.tables.c_user.key-generator.type=SNOWFLAKE
四、Sharding-Jdbc分布式事务
四-1.分布式事务介绍
常见的分布式事务的解决方案:
1. 2PC模式(强一致性)
分为两个阶段:阶段 1:准备阶段,阶段 2:提交阶段
2. 3PC模式(强一致性)
分为两个阶段:
- 阶段1:canCommit*
协调者向参与者发送 commit 请求,参与者如果可以提交就返回 yes 响应,否则返回 no 响应。 - 阶段2:preCommit*
协调者根据阶段 1 canCommit 参与者的反应情况执行预提交事务或中断事务操作。
1)参与者均反馈 yes:协调者向所有参与者发出 preCommit 请求,参与者收到preCommit 请求后,执行事务操作,但不提交;将 undo 和 redo 信息记入事务日志中;各参与者向协调者反馈 ack 响应或 no 响应,并等待最终指令。
2)任何一个参与者反馈 no或等待超时:协调者向所有参与者发出 abort 请求,无论收到
协调者发出的 abort 请求,或者在等待协调者请求过程中出现超时,参与者均会中断事
务。 - 阶段3:do Commit*
该阶段进行真正的事务提交,根据阶段 2 preCommit反馈的结果完成事务提交或中断操作。
相比2PC模式,3PC模式降低了阻塞范围,在等待超时后协调者或参与者会中断事务。避免了协调
者单点问题,阶段 3 中协调者出现问题时(比如网络中断等),参与者会继续提交事务。
3. XA(强一致性)
XA之所以需要引入事务管理器,是因为在分布式系统中,从理论上讲两台机器理论上无法达到一致的状态,需要引入一个单点进行协调。由全局事务管理器管理和协调的事务,可以跨越多个资源(数据库)和进程。
事务管理器用来保证所有的事务参与者都完成了准备工作(第一阶段)。如果事务管理器收到所有参与者都准备好的消息,就会通知所有的事务都可以提交了(第二阶段)。MySQL 在这个XA事务中扮演的是参与者的角色,而不是事务管理器。
4、 TCC模式(最终一致性)[适合微服务的架构]
TCC 是服务化的两阶段
编程模型,其 Try、Confirm、Cancel 3 个方法均由业务编码实现:
- 操作作为一阶段,负责资源的检查和预留;
- Confirm 操作作为二阶段提交操作,执行真正的业务;
- Cancel 是预留资源的取消;
TCC 模式相比于 XA,解决了如下几个缺点: - 解决了协调者单点,由主业务方发起并完成这个业务活动。业务活动管理器可以变成多点,
引入集群。 - 同步阻塞:引入超时机制,超时后进行补偿,并且不会锁定整个资源,将资源转换为业务逻
辑形式,粒度变小。 - 数据一致性,有了补偿机制之后,由业务活动管理器控制一致性。
5、 消息队列模式(最终一致性)[TCC模式的一种实现]
用消息中间件充当事务管理器,可以将调用采取异步实现。
基于TCC模式,消息中间件可以基于 Kafka、RocketMQ 等
消息队列。此方案的核心是将分布式事务拆分成本地事务进行处理,将需要分布式处理的任务通过消息日志的方式来异步执行。消息日志可以存储到本地文本、数据库或MQ中间件,再通过业务规则人工发起重试。
事务的处理流程:
- 步骤1:事务主动方处理本地事务。
事务主动方在本地事务中处理业务更新操作和MQ写消息操作。 - 步骤 2:事务主动方通过消息中间件,通知事务被动方处理事务通知事务待消息。事务主动方主动写消息到MQ,事务消费方接收并处理MQ中的消息。
- 步骤 3:事务被动方通过MQ中间件,通知事务主动方事务已处理的消息,事务主动方根据反馈结果提交或回滚事务。
场景业务:
下单:事务主动方:下单操作-》本地库存服务处理,往MQ里添加消息,利用消息向被动方(订单服务)通知订单新增一条数据,订单服务收到消息后在订单表里追加信息,追加成功后,这时它就要向MQ里写入消息通知库存服务,成功的话两个都提交,失败的话两个都回滚。
为了数据的一致性,当流程中遇到错误需要重试,容错处理规则如下:
- 当步骤 1 处理出错,事务回滚,相当于什么都没发生。
- 当步骤 2 处理出错,由于未处理的事务消息还是保存在事务发送方,可以重试或撤销本地业务操作。
- 如果事务被动方消费消息异常,需要不断重试,业务处理逻辑需要保证幂等。
- 如果是事务被动方业务上的处理失败,可以通过MQ通知事务主动方进行补偿或者事务回滚。
- 如果多个事务被动方已经消费消息,事务主动方需要回滚事务时需要通知事务被动方回滚。
需要程序员自己实现
6.Saga模式(最终一致性)
一个Saga事务是一个有多个短时事务组成的长时的事务。
在分布式事务场景下,我们把一个Saga分布式事务看做是一个由多个本地事务组成的事务,每个本地事务都有一个与之对应的补偿事务。
在Saga事务的执行过程中,如果某一步执行出现异常,Saga事务会被终止,同时会调用对应的补偿事务完成相关的恢复操作,这样保证Saga相关的本地事务要么都是执行成功,要么通过补偿恢复成为事务执行之前的状态。(自动反向补偿机制)。
Saga 事务基本协议如下:
- 每个 Saga 事务由一系列幂等的有序子事务(sub-transaction) Ti 组成
- 每个 Ti 都有对应的幂等补偿动作 Ci,补偿动作用于撤销 Ti 造成的结果。
Saga是一种补偿模式,它定义了两种补偿策略:
1)、向前恢复(forward recovery):对应于上面第一种执行顺序,发生失败进行重试,适用于必须要成功的场景。
2)、向后恢复(backward recovery):对应于上面提到的第二种执行顺序,发生错误后撤销掉之前所有成功的子事务,使得整个 Saga 的执行结果撤销。
Seata框架
Seata(Simple Extensible Autonomous Transaction Architecture)是一套一站式分布式事务解决方案,是阿里集团和蚂蚁金服联合打造的分布式事务框架。Seata目前的事务模式有AT、TCC、Saga和XA,默认是AT模式,AT本质上是2PC协议的一种实现。
Seata AT事务模型包含TM(事务管理器),RM(资源管理器),TC(事务协调器)。其中TC是一个独立的服务需要单独部署,TM和RM以jar包的方式同业务应用部署在一起,它们同TC建立长连接,在整个事务生命周期内,保持RPC通信。
- 全局事务的发起方作为TM,全局事务的参与者作为RM
- TM负责全局事务的begin和commit/rollback
- RM负责分支事务的执行结果上报,并且通过TC的协调进行commit/rollback。
在 Seata 中,AT时分为两个阶段的,第一阶段,就是各个阶段本地提交操作;第二阶段会根据第一阶段的情况决定是进行全局提交还是全局回滚操作。具体的执行流程如下: - TM 开启分布式事务,负责全局事务的begin和commit/rollback(TM 向 TC 注册全局事务记录);
- RM 作为参与者,负责分支事务的执行结果上报,并且通过TC的协调进行commit/rollback(RM 向 TC 汇报资源准备状态 );
- RM分支事务结束,事务一阶段结束;
- 根据TC 汇总事务信息,由TM发起事务提交或回滚操作;
- TC 通知所有 RM 提交/回滚资源,事务二阶段结束;
(小的事务通过XID进行关联,TM向TC注册)
四-2.ShardingSphere整合事务
(1)ShardingSphere整合Saga事务【saga是一种补偿协议】
ShardingSphere的柔性事务已通过第三方servicecomb-saga组件实现的,通过SPI机制注入使用。
ShardingSphere是基于反向SQL技术实现的反向补偿操作
ShardingSphere支持以下功能:
- 完全支持跨库事务
- 支持失败SQL重试及最大努力送达
- 支持反向SQL、自动生成更新快照以及自动补偿
- 默认使用关系型数据库进行快照及事务日志的持久化,支持使用SPI的方式加载其他类型的持久化
- Init(Saga引擎初始化)
包含Saga柔性事务的应用启动时,saga-actuator引擎会根据saga.properties的配置进行初始化的流程。 - Begin(开启Saga全局事务)
每次开启Saga全局事务时,将会生成本次全局事务的上下文(SagaTransactionContext),事务上下文记录了所有子事务的正向SQL和逆向SQL,作为生成事务调用链的元数据使用。 - 执行物理SQL
在物理SQL执行前,ShardingSphere根据SQL的类型生成逆向SQL,这里是通过Hook的方式拦截Parser的解析结果进行实现。 - Commit/rollback(提交Saga事务)
提交阶段会生成Saga执行引擎所需的调用链路图,commit操作产生ForwardRecovery(正向SQL补偿)任务,rollback操作产生BackwardRecovery任务(逆向SQL补偿)。
(2)ShardingSphere整合Seata框架
分布式事务的实现目前主要分为两阶段的XA强事务和BASE柔性事务。也支持补偿,(Saga不支持隔离级别)
- Init(Seata引擎初始化)
包含Seata柔性事务的应用启动时,用户配置的数据源会按seata.conf的配置,适配成Seata事务所需的DataSourceProxy,并且注册到RM中。 - Begin(开启Seata全局事务)
TM控制全局事务的边界,TM通过向TC发送Begin指令,获取全局事务ID,所有分支事务通过此全局事务ID,参与到全局事务中;全局事务ID的上下文存放在当前线程变量中。 - 执行分片物理SQL
处于Seata全局事务中的分片SQL通过RM生成undo快照,并且发送participate指令到TC,加入到全局事务中。ShardingSphere的分片物理SQL是按多线程方式执行,因此整合Seata AT事务时,需要在主线程和子线程间进行全局事务ID的上下文传递,这同服务间的上下文传递思路完全相同。 - Commit/rollback(提交Seata事务)
提交Seata事务时,TM会向TC发送全局事务的commit和rollback指令,TC根据全局事务ID协调所
有分支事务进行commit和rollback。
四-3.ShardingSphere整合事务实战
ShardingSphere整合了XA、Saga和Seata模式后,为分布式事务控制提供了极大的便利,采用以下统一模式进行使用。
- 引入Maven依赖
<!--XA模式-->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-transaction-xa-core</artifactId>
</dependency>
<!--Saga模式-->
<dependency>
<groupId>io.shardingsphere</groupId>
<artifactId>sharding-transaction-base-saga</artifactId>
</dependency>
<!--Seata模式模式-->
<dependency>
<groupId>org.apache.shardingsphere</groupId>
<artifactId>sharding-transaction-base-seata-at</artifactId>
</dependency>
- 开启spring事务管理
- 测试
@Test
@Transactional
@ShardingTransactionType(TransactionType.XA)
//@ShardingTransactionType(TransactionType.BASE)Sega和Seata
public void testAddDetail()
{}
五.Sharding拓展二
1、SPI加载剖析
在Apache ShardingSphere中,很多功能实现类的加载方式是通过SPI注入的方式完成的。 ServiceProvider Interface (SPI)是Java提供的一套被第三方实现或扩展的API,它可以用于实现框架扩展或组件替换。它将装配的控制权转移到程序之外。
Apache ShardingSphere所有通过SPI方式载入的功能模块:
- SQL解析
- 数据库协议
- 数据脱敏
- 分布式主键
- 分布式事务
分布式事务的接口主要用于规定如何将分布式事务适配为本地事务接口。
主要接口为ShardingTransactionManager,其内置实现类有XAShardingTransactionManagerSeataATShardingTransactionManager。 - XA事务管理器
- 注册中心
2、 Sharding-Proxy实战
- 下载Sharding-Proxy的最新发行版;
- 解压缩后修改conf/server.yaml和以config-前缀开头的文件,进行分片规则、读写分离规则配置
编辑%SHARDING_PROXY_HOME%\conf\config-xxx.yaml
编辑%SHARDING_PROXY_HOME%\conf\server.yaml - 引入依赖jar
如果后端连接MySQL数据库,需要下载MySQL驱动, 解压缩后将mysql-connector-java-5.1.48.jar拷贝到${sharding-proxy}\lib目录。如果后端连接PostgreSQL数据库,不需要引入额外依赖。
1)搭建步骤
1.配置server.yaml
authentication:
users:
root:
password: root
authorizedSchemas: lagou_db
#
props:
max.connections.size.per.query: 1
acceptor.size: 16 # The default value is available processors count * 2.
executor.size: 16 # Infinite by default.
proxy.frontend.flush.threshold: 128 # The default value is 128.
# # LOCAL: Proxy will run with LOCAL transaction.
# # XA: Proxy will run with XA transaction.
# # BASE: Proxy will run with B.A.S.E transaction.
proxy.transaction.type: LOCAL
proxy.opentracing.enabled: false
proxy.hint.enabled: false
query.with.cipher.column: true
sql.show: true
allow.range.query.with.inline.sharding: false
2.config-sharding.yaml连接信息配置
设置具体分片
schemaName: lagou_db
#
dataSources:
ds_0:
url: jdbc:mysql://192.168.142.128:3306/lagou1?serverTimezone=UTC&useSSL=false
username: root
password: root
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
ds_1:
url: jdbc:mysql://192.168.142.129:3306/lagou2?serverTimezone=UTC&useSSL=false
username: root
password: root
connectionTimeoutMilliseconds: 30000
idleTimeoutMilliseconds: 60000
maxLifetimeMilliseconds: 1800000
maxPoolSize: 50
shardingRule:
tables:
t_order:
actualDataNodes: ds_${0..1}.position
databaseStrategy:
inline:
shardingColumn: id
algorithmExpression: ds_${id % 2}
keyGenerator:
type: SNOWFLAKE
column: id
3.使用客户端工具连接。如: mysql -h 127.0.0.1 -P 3307 -u root -p root
3、 Mycat 简介实战
1、 Mycat安装
- 提示:需要先安装jdk
- 下载Mycat-server工具包
- 解压Mycat工具包
tar -zxvf Mycat-server-1.6.7.5-release-20200410174409-linux.tar.gz - 进入mycat/bin,启动Mycat
启动命令:./mycat start
停止命令:./mycat stop
重启命令:./mycat restart
查看状态:./mycat status - 访问Mycat
mysql -uroot -proot -h127.0.0.1 -P8066
2 、分库分表
Mycat常用分片规则如下:
- 时间类:按天分片、自然月分片、单月小时分片
- 哈希类:Hash固定分片、日期范围Hash分片、截取数字Hash求模范围分片、截取数字Hash分片、一致性Hash分片
- 取模类:取模分片、取模范围分片、范围求模分片
- 其他类:枚举分片、范围约定分片、应用指定分片、冷热数据分片
3、配置
1)server.xml
配置用户信息以及主键生成类型
2)修改schema.xml
3)修改rule.xml
4)启动之前先做如下操作
返回wrapper | OpenSCManager failed - 拒绝访问。 (0x5),这是因为当前用户权限不够,运行cmd时以管理员身份运行即可。
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容。