servicecomb-pack分布式事务解决方案之学习之路(一):saga和tcc-spring-demo

本片文章是一篇servicecomb-pack的使用教程说明,理论知识会另起一篇文章再详细说明(架构理论传送门1,架构理论传送门2)

servicecomb是华为开源的一个微服务框架,后进入Apache软件基金会孵化,现已毕业,是apache顶级开源项目,而servicecomb-pack是servicecomb孵化的三个子项目之一,是分布式事务最终一致性解决方案,0.3.0版本之前叫saga,现改名为servicecomb-pack,支持saga和tcc两种分布式事务协议,相关理论知识请移步(传送门),本文主要介绍saga模式,下一篇介绍tcc模式

1.先配置和运行alpha-server

注意:alpha-server目前并没有提供starter,因此需要从GitHub上获取源码本地自行编译运行

源码获取

Github地址:https://github.com/apache/servicecomb-pack

git命令:$ git clone https://github.com/apache/servicecomb-pack.git

修改配置文件

找到alpha-server/src/main/resource/application.yaml,修改datasource信息为本地信息即可

本地构建alpha-server

$ cd servicecomb-pack

只构建可执行文件(推荐

$ mvn clean install -DskipTests -Pspring-boot-2

同时构建可执行文件和docker镜像

$ mvn clean install -DskipTests -Pdocker,spring-boot-2

 

同时构建可执行文件以及pack发行包

$ mvn clean install -DskipTests -Prelease,spring-boot-2

在执行上面任一指令后,可在alpha/alpha-server/target/saga/alpha-server-${version}-exec.jar中找到alpha-server的可执行jar包

启动alpha-server

通过docker运行:

docker run -d -p 8080:8080 -p 8090:8090 -e "JAVA_OPTS=-Dspring.profiles.active=prd -Dspring.datasource.url=jdbc:postgresql://${host_address}:5432/saga?useSSL=false" alpha-server:${saga_version}

通过可执行文件运行:

java -Dspring.profiles.active=prd -D"spring.datasource.url=jdbc:postgresql://${host_address}:5432/saga?useSSL=false" -jar alpha-server-${saga_version}-exec.jar

注意:请在执行命令前将${saga_version}${host_address}更改为实际值

至此,alpha-server全局事务管理器已经启动成功

替换postgresql为mysql

alpha-server默认使用postgresql,因此如想替换成mysql需以下步骤:

  • 安装并运行mysql
  • 修改pom文件,添加依赖:alpha-server/pom.xml,添加mysql依赖(因为配置文件中需要配置driver信息)

    dependency>
      mysql
      mysql-connector-java
      runtime
      8.0.15
    
    

     

 

  • 找到alpha-server/src/main/resource/application.yaml,修改datasource信息为本地信息即可;注:url需添加serverTimezone,并增加driver-class-name属性

    spring:
      profiles: mysql
      datasource:
        username: ${username}
        password: ${password}
        url: jdbc:mysql://${host_address}:${port}/${database_name}?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=false
        platform: mysql
        continue-on-error: false
        driver-class-name: com.mysql.cj.jdbc.Driver
      jpa:
        properties:
          eclipselink:
            ddl-generation: none
    

     

注意:${username},${password},${host_address},${port},${database_name}需替换为实际值

  • 本地构建alpha-server(和上面步骤一致)
  • 启动alpha-server(和上面步骤一致)

2.Omega配置

添加依赖


    org.apache.servicecomb.pack
    omega-spring-starter
    ${servicecomb-pack.version}


    org.apache.servicecomb.pack
    omega-spring-cloud-consul-starter
    ${servicecomb-pack.version}


    org.apache.servicecomb.pack
    omega-transport-resttemplate
    ${servicecomb-pack.version}

注意:请将${servicecomb-pack.version}更改为实际的版本号(目前最新release为0.4.0)

修改配置文件

添加这一配置即可,其他应用配置自行添加,address可根据alpha-server中的配置实际添加

# 配置alpha-service 集群/单机 服务访问地址
alpha:
  cluster:
    address: localhost:8080

saga模式demo配置

添加saga的注解以及相关的补偿方法配置

  • 在应用入口添加@ EnableOmega 注解来初始化Omega的配置并与alpha-server建立连接(@EnableOmega注解在当前版本已经标注为过时注解,但是不妨碍功能,后续应该会把注解转换为在配置文件中配置开关属性,目前版本中还没开始这种做)
@SpringBootApplication
@EnableOmega
public class CarApplication {

    public static void main(String[] args) {
        SpringApplication.run(CarApplication.class, args);
    }

}
  • 在全局事务的起点添加@SagaStart注解标注这是saga事务的start
@SagaStart(timeout = 5)  //开启saga分布式事务,默认情况下,超时设置需要显示声明才生效
@GetMapping("/booking/{name}/{rooms}/{cars}")
public String booking(@PathVariable String name,@PathVariable Integer rooms,
                    @PathVariable Integer cars) throws Exception{}

注意:默认情况下,超时设置需要显示声明才能生效

  • 在子事务处添加@ Compensable 注解并指明其对应的补偿方法
@Override
@Transactional
@Compensable(timeout = 5, compensationMethod = "cancel")
public CarBooking order(CarBooking carBooking) {
    return repository.save(carBooking);
}

补偿方法

//补偿逻辑 入参和try方法一致
    @Transactional
    public void cancel(CarBooking carBooking) {
        //demo只进行取消/删除 设置状态; 实际开发中可针对实际业务进行逻辑编码
        //修改状态
        carBooking.setCancelled(Boolean.TRUE);
        repository.save(carBooking);

        //删除记录
//        repository.delete(toSpecification(carBooking));
    }

注意:实现的服务和补偿方法必须满足幂等的要求

注意:默认情况下,超时需要显示声明

注意:若全局事务起点与子事务重合,需同时声明@SagaStart和@Compensable注解

注意:补偿方法的入参必须与try方法入参一致,否则启动时会报错(alpha-server找不到补偿方法)

至此,正常启动服务即完成saga模式配置

tcc模式demo配置

  • 在应用入口处添加@EnableOmega注解
    @SpringBootApplication
    @EnableOmega
    public class OrderingApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(OrderingApplication.class, args);
        }
    
    }
    

     

  • 在全局事务的起点添加@TccStart注解标注这是tcc事务的start
    @TccStart(timeout = 5)  //当前版本的tcc还不支持timeout
    @PostMapping("/order/{userName}/{productName}/{productUnit}/{unitPrice}")
    public String order(@PathVariable String userName,@PathVariable String productName,
                        @PathVariable Integer productUnit,@PathVariable Integer unitPrice) throws Exception{}
    

    注意:当前版本tcc还不支持timeout

  • 在子事务处添加@Participate注解并指明confirm和cancel方法
    @Override
    @Transactional
    @Participate(confirmMethod = "confirm", cancelMethod = "cancel")
    public void reserve(ProductOrder productOrder) {
        Product product = new Product();
        product.setName(productOrder.getProductName());
        product = productRepository.findOne(toSpecification1(product)).get();
        if (product.getInStock() >= productOrder.getUnits()) {
            product.setInStock(product.getInStock() - productOrder.getUnits());
            productRepository.save(product);
    
            productOrderRepository.save(productOrder);
        } else {
            throw new IllegalArgumentException("The Product is out of stock!");
        }
    }
    

    确认方法

    public void confirm(ProductOrder productOrder) {
        ......
    }
    

    补偿方法

    public void cancel(ProductOrder productOrder) {
        ......
    }
    

    注意:confirm和cancel方法的入参必须和try方法一致

    至此,正常启动服务即完成tcc模式配置

到此,saga和tcc已经基本搭建完成

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(分布式事务)