简单的分布式事务

1、了解CAP理论

     1、一致性

            实现目标:当数据分布在多个节点上,从任意节点读取都是最新的数据。

            例如:数据库做了读写分离,写入master的数据,要在slave上查询出来的是最新的,也就是一致性

            实现方式: 当写入主数据库时,将从数据库锁定,等写入完成,解锁从数据库。如果同步失败,返回错误信息

     2、可用性

             实现目标:从数据库中查询可以立刻查询出结果,不允许出现超时或报错

             实现方式:保证可用性,就不可以将数据库锁定。返回数据时,即使是旧的数据,也要返回,就是不能返回错误信息 

     3、分区容忍性

              实现目标:当项目分布在多个服务器上,需要用http请求访问,可能访问时出现问题,但是即使出现错误,也要可以对外提供服务

              实现方式:1、尽量使用异步来操作。2、部署主从数据库,保证一个节点挂,其他节点可以顶上

     4、结论

            以上可知,分区容忍性是必须具备的。在保证分区容忍性之后。来看a和c。

            c是一致性,要保证服务查询到的是最新的数据,就要锁库,但是a是可用性,可用性特点是即使是旧数据也要正常返回,那么就是冲突的,我们只能保证其中一个,以下为组合方式:

            1、AP(常用)

               保证可用性和分区容忍性 

               例如:转账,今日转账,明日才能收到金额。用户也是可以接收的。

             2、CP

               保证一致性和分区容忍性

               数据一定会同时进行操作,这边打钱,那边实时收到款

             3、CA

                 数据库不进行分区,也就不再是一个分布式系统了

2、base理论

       1、理解强一致性和最终一致性的区别

            1、强一致性:

                 a银行扣款成功,b银行要实时收到钱。即使中间出现了错误,也要返回一个错误信息,同时回滚

            2、最终一致性:

                 a银行扣款成功,b银行可以不实时收到钱,状态会变成转账中,如果转账成功,b银行实时收到钱,如果失败,a银行退回金额

      2、base理论理解

             base理论是基本可用,软状态,最终一致性的缩写。是对ap理论的拓展,允许数据一段时间内是不一致性的,但要达到最终一致性。这种方式可以理解为 柔性事务

             基本可用:

                  当其中一个服务出现故障时,其他服务可以正常使用

             软状态: 

                   例如支付中,扣款中等状态

              最终一致性

                  最终状态会变成扣款成功和扣款失败

3、seata使用

      1、先了解几个概念

               事务协调器(TC):单独部署,协调各个事务的提交和回滚操作

               事务管理器(TM):嵌入服务中,负责开启事务,也就是添加事务注解,向事务协调器发送提交和回滚的指令

               服务(RM):每个参与事务的服务

       2、seata执行流程

             案例:a向b用户转账

                       正常流程:

                       增加注解到发起方:a发起的扣款,所以a负责开启事务,service方法上加入@GlobalTransactional开启全局事务,并返回全局事务id。至此,全局事务开启完成

                       1、a服务开始扣减金额操作前,携带全局事务id向事务协调器注册一个分支事务并返回一个分支事务id。

                       2、有了分支事务id,开始执行扣减金额操作,执行后写入undo_log表中数据(表中主要记录分支事务id,全局事务id,修改前到修改后等信息),并提交分支事务,扣减金额完成

                       3、a服务执行完成后,向b服务发出增加金额请求,请求中携带全局事务id 

                       4、b服务执行增加金额前,携带全局事务id向事务协调器注册一个分支事务并返回一个分支事务id。

                       5、执行增加金额操作,记录到undo_log中,提交分支事务。

                       6、所有子服务执行完成,事务管理器提交全局事务,提交完成后,删除每个服务中对应的undo_log记录

 

                      异常流程:

                       1、如果有服务执行中出现了异常,就会向事务协调器发送回滚消息。之后执行所有服务的回滚操作

                       2、回滚:由于每个undo_log中存储了每个服务的修改前消息和修改后消息。执行每个服务的反向操作,也就是自动生成一条反向的sql

                      ‘’

                 

       3、启动流程

              1、启动事务协调器

               cmd下: seata-server.bat -p 8888 -m file

              2、每个服务引入seata包

        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-seata</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.47</version>
        </dependency>

               3、服务的数据库创建undo_log表

CREATE TABLE `undo_log` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `branch_id` bigint(20) NOT NULL,
  `xid` varchar(100) NOT NULL,
  `context` varchar(128) NOT NULL,
  `rollback_info` longblob NOT NULL,
  `log_status` int(11) NOT NULL,
  `log_created` datetime NOT NULL,
  `log_modified` datetime NOT NULL,
  `ext` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `ux_undo_log` (`xid`,`branch_id`)
) ENGINE=InnoDB AUTO_INCREMENT=169 DEFAULT CHARSET=utf8

                 4、将seata-server-0.7.1\conf下的file.conf和registry.conf拷到服务resources下

                      file.conf修改:

service {
  #vgroup_mapping.修改为项目服务名称-fescar-service-group
  #default 为协调器名称
  vgroup_mapping.seata-demo-bank1-fescar-service-group = "default"
  #事务协调器地址
  default.grouplist = "127.0.0.1:8888"
  #不开启降级
  enableDegrade = false
  #disable
  disable = false
}

               5、application.yml中添加mysql数据源配置

spring:
  ##################### DB #####################
  datasource:
    ds0:
      url: jdbc:mysql://localhost:3306/bank1?useUnicode=true
      username: root
      password: 1234
      type: com.alibaba.druid.pool.DruidDataSource
      driver-class-name: com.mysql.jdbc.Driver
      initialSize: 5
      minIdle: 5
      maxActive: 20
      maxWait: 60000
      timeBetweenEvictionRunsMillis: 60000
      minEvictableIdleTimeMillis: 300000
      validationQuery: SELECT user()
      testWhileIdle: true
      testOnBorrow: false
      testOnReturn: false
      poolPreparedStatements: true
      connection-properties: druid.stat.mergeSql:true;druid.stat.slowSqlMillis:5000

            6、添加DatabaseConfiguration.java 来使用该配置并与事务协调器进行交互

import com.alibaba.druid.pool.DruidDataSource;
import io.seata.rm.datasource.DataSourceProxy;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;

import javax.sql.DataSource;

@Configuration
public class DatabaseConfiguration {


    private final ApplicationContext applicationContext;

    public DatabaseConfiguration(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }


    @Bean
    @ConfigurationProperties(prefix = "spring.datasource.ds0")
    public DruidDataSource ds0() {
        DruidDataSource druidDataSource = new DruidDataSource();
        return druidDataSource;
    }


    @Primary
    @Bean
    public DataSource dataSource(DruidDataSource ds0)  {
        DataSourceProxy pds0 = new DataSourceProxy(ds0);
        return pds0;
    }
}

             7、在service方法上增加@GlobalTransactional和@transactional注解即可

 

4、了解TCC理论

      1、什么是TCC

              tcc是try(预处理),confirm(确认),cancel(取消)。要求每个事务都有三个操作

              try:业务检查阶段

              confirm:业务确认阶段,只要try成功,confirm肯定会成功,如果不成功需要重试,还不行只能人工参与

              cancel:业务取消阶段,只要try成功,cancel肯定会成功,如果不成功需要重试,还不行只能人工参与

     2、案例

               a向b转账,a服务和b服务都会有try,confirm, cancel,tcc需要做严密的幂等操作,也就是要保证每次访问接口都是同样的结果

a服务:       
   try:
      判断是否已经执行try,如果执行过,就不再执行
      判断是否已经执行了cancel和confirm,如果执行了,就不执行了
      扣减金额,如果扣减失败,就抛异常到cancel
   confirm:
      空,因为try已经执行了扣减金额操作
   cancel:
      判断是否已经执行了try,没有执行就不执行了
      判断有没有执行过cancel,执行过就不执行了
      把扣除的金额添加回来
 

b服务:
   try:
      空,a服务已经扣减成功,所以b服务必须成功
   confirm:
      判断是否已经增加过
      增加金额
   cancel:
      空

     3、编写代码(hmily框架实现)

              1、导入依赖

        <dependency>
            <groupId>org.dromara</groupId>
            <artifactId>hmily-springcloud</artifactId>
            <version>2.0.4-RELEASE</version>
        </dependency>

             2、创建hmily数据库,记录hmily框架的数据。hmily框架运行时会自动创建表

CREATE DATABASE `hmily` CHARACTER SET 'utf8' COLLATE 'utf8_general_ci';

             3、添加配置

org:
  dromara:
    hmily :
      serializer : kryo
      recoverDelayTime : 30
      retryMax : 30
      scheduledDelay : 30
      scheduledThreadMax :  10
      repositorySupport : db
      started: true  #事务发起方为true,接收方为false
      hmilyDbConfig :
        driverClassName  : com.mysql.jdbc.Driver
        url :  jdbc:mysql://localhost:3306/hmily?useUnicode=true
        username : root
        password : 1234

             4、发起方添加注解@EnableAspectJAutoProxy

             5、调用方feign接口上增加@Hmily,将全局事务id发送给被调用者

             6、在service上增加@Hmily(confirmMethod = "confirmMethod ", cancelMethod = "cancelMethod ") 

                   在本类中增加confirmMethod和cancelMethod两个方法

5、消息中间件的最终一致性

           可以使用rocketmq来解决消息中间件,实现事务

          参考链接:https://blog.csdn.net/qq_38384460/article/details/114692078

6、最大努力通知

      1、交互流程

            1、b服务完成加钱后,通知a系统转账成功,如果通知失败,则按照策略进行重复通知

            2、a服务收到结果后,修改状态为转账成功

            3、如果还是没有通知,需要给a服务提供是否转账成功的接口。

               

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。
Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统。以下是Go语言的一些主要特点和优势: 简洁性:Go语言的语法简单直观,易于学习和使用。它避免了复杂的语法特性,如继承、重载等,转而采用组合和接口来实现代码的复用和扩展。 高性能:Go语言具有出色的性能,可以媲美C和C++。它使用静态类型系统和编译型语言的优势,能够生成高效的机器码。 并发性:Go语言内置了对并发的支持,通过轻量级的goroutine和channel机制,可以轻松实现并发编程。这使得Go语言在构建高性能的服务器和分布式系统时具有天然的优势。 安全性:Go语言具有强大的类型系统和内存管理机制,能够减少运行时错误和内存泄漏等问题。它还支持编译时检查,可以在编译阶段就发现潜在的问题。 标准库:Go语言的标准库非常丰富,包含了大量的实用功能和工具,如网络编程、文件操作、加密解密等。这使得开发者可以更加专注于业务逻辑的实现,而无需花费太多时间在底层功能的实现上。 跨平台:Go语言支持多种操作系统和平台,包括Windows、Linux、macOS等。它使用统一的构建系统(如Go Modules),可以轻松地跨平台编译和运行代码。 开源和社区支持:Go语言是开源的,具有庞大的社区支持和丰富的资源。开发者可以通过社区获取帮助、分享经验和学习资料。 总之,Go语言是一种简单、高效、安全、并发的编程语言,特别适用于构建高性能的服务器和分布式系统。如果你正在寻找一种易于学习和使用的编程语言,并且需要处理大量的并发请求和数据,那么Go语言可能是一个不错的选择。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值