ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

TCC事务模型

2021-11-16 11:32:33  阅读:192  来源: 互联网

标签:事务 pay 模型 springframework annotation org import com TCC


原理介绍

TCC事务机制相对于传统事务机制(X/Open XA Two-Phase-Commit),其特征在于它不依赖资源管理器(RM)对XA的支持,而是通过对(由业务系统提供的)业务逻辑的调度来实现分布式事务。主要由三步操作,Try: 尝试执行业务、 Confirm:确认执行业务、 Cancel: 取消执行业务。

模式特点

  • 该模式对代码的嵌入性高,要求每个业务需要写三种步骤的操作。
  • 该模式对有无本地事务控制都可以支持使用面广。
  • 数据一致性控制几乎完全由开发者控制,对业务开发难度要求高。

使用场景

没有带事务的中间件,如:redis

项目实战

pom.xml和application.yml文与LCN的一致

模拟Tcc组合redis

项目组合:

  • lcn-tm:事务管理者
  • lcn-order:事务发起者
  • lcn-pay:事务参与者
  • cloud-eureka:注册中心

事务发起者和事务参与者都是TCC

发起者代码

package com.dandan.lcnorder.controller;

import com.codingapi.txlcn.tc.annotation.LcnTransaction;
import com.codingapi.txlcn.tc.annotation.TccTransaction;
import com.dandan.lcnorder.dao.TblOrderDao;
import com.dandan.lcnorder.entity.TblOrder;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * 模拟Tcc组合redis
 */
@RestController
public class OrderTccRedisController {

    @Autowired
    private TblOrderDao tblOrderDao;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @PostMapping("/add-order-tcc-redis")
    @Transactional(rollbackFor = Exception.class)
    @TccTransaction
    public String add(@RequestBody TblOrder bean){

        JSONObject date = new JSONObject();
        date.put("payName",bean.getOrderName()+"pay");
        restTemplate.postForEntity("http://lcn-pay/add-pay-tcc-redis",date,String.class);

        TblOrder tblOrder = new TblOrder();
        tblOrder.setId(1);
        tblOrder.setOrderName("新");

        BoundValueOperations<String, String> order = redisTemplate.boundValueOps("order");
        order.set("order-value");

        tblOrderDao.updateByPrimaryKey(tblOrder);
        int i = 1/0;
        return "新增订单成功";
    }

    public String confirmAdd(TblOrder bean){
        System.out.println("add 确认线程名:"+Thread.currentThread().getName());
        System.out.println("order confirm ");
        return "confirm 订单成功";
    }

////    private static Map<String,Integer> maps = new HashMap<>();
//
//    private ThreadLocal<Integer> ids = new ThreadLocal<>();

    public String cancelAdd(TblOrder bean){
        System.out.println("add 取消线程名:"+Thread.currentThread().getName());
        TblOrder tblOrder = new TblOrder();
        tblOrder.setId(1);
        tblOrder.setOrderName("旧");

        tblOrderDao.updateByPrimaryKey(tblOrder);

        redisTemplate.delete("order");
        System.out.println("order cancel ");
        return "cancel 订单成功";
    }
}

参与者代码

package com.dandan.lcnpay.controller;

import com.codingapi.txlcn.tc.annotation.TccTransaction;
import com.dandan.lcnpay.dao.TblPayDao;
import com.dandan.lcnpay.entity.TblPay;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * 模拟Tcc组合mysql,不建议用,代码复杂度太高,使用LCN更简单
 */
@RestController
public class PayTccController {


    @Autowired
    private TblPayDao tblPayDao;

    @PostMapping("/add-pay-tcc")
    @Transactional(rollbackFor = Exception.class)
    @TccTransaction
    public String addPay(@RequestBody TblPay bean){
        tblPayDao.insert(bean);
        Integer id = bean.getId();
        maps.put("a",id);
//        int i = 1/0;
        return "新增支付成功";

    }
    public String confirmAddPay(TblPay bean){
        System.out.println("pay confirm");
        return "新增支付成功";

    }
    private static Map<String,Integer> maps = new HashMap<>();

    /**
     * 逆sql
     * @param bean
     * @return
     */
    public String cancelAddPay(TblPay bean){
        Integer a = maps.get("a");
        System.out.println("a:"+a);
        System.out.println("pay cancel");
        tblPayDao.deleteByPrimaryKey(a);
        return "取消支付成功";

    }
}

事务发起者是LCN,参与者是TCC

发起者代码

package com.dandan.lcnorder.controller;

import com.codingapi.txlcn.tc.annotation.LcnTransaction;
import com.dandan.lcnorder.dao.TblOrderDao;
import com.dandan.lcnorder.entity.TblOrder;
import net.sf.json.JSONObject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * 模拟Tcc组合redis,LCN组合sql
 * client1使用LCN
 * client2使用TCC
 */
@RestController
public class OrderTccRedisController2 {

    @Autowired
    private TblOrderDao tblOrderDao;

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @PostMapping("/add-order-tcc-redis2")
    @Transactional(rollbackFor = Exception.class)
    @LcnTransaction
    public String add(@RequestBody TblOrder bean){

        JSONObject date = new JSONObject();
        date.put("payName",bean.getOrderName()+"pay");
        restTemplate.postForEntity("http://lcn-pay/add-pay-tcc-redis",date,String.class);

        TblOrder tblOrder = new TblOrder();
        tblOrder.setId(1);
        tblOrder.setOrderName("新");

        tblOrderDao.updateByPrimaryKey(tblOrder);
        int i = 1/0;
        return "新增订单成功";
    }
}

参与者代码

package com.dandan.lcnpay.controller;

import com.dandan.lcnpay.dao.TblPayDao;
import com.dandan.lcnpay.entity.TblPay;
import com.dandan.lcnpay.service.RedisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class PayTccRedisController {


    @Autowired
    private TblPayDao tblPayDao;

    @Autowired
    private RedisService redisService;

    @PostMapping("/add-pay-tcc-redis")
    @Transactional(rollbackFor = Exception.class)
    public String addPay(@RequestBody TblPay bean){
        redisService.addPay(null);
//        int i = 1/0;
        return "新增支付成功";
    }
}

RedisService代码

package com.dandan.lcnpay.service;

import com.codingapi.txlcn.tc.annotation.TccTransaction;
import com.dandan.lcnpay.entity.TblPay;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.BoundValueOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestBody;

import java.util.HashMap;

@Service
public class RedisService {

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @TccTransaction
    public String addPay(@RequestBody TblPay bean){
        BoundValueOperations<String, String> pay = redisTemplate.boundValueOps("pay");
        pay.set("pay-value");
//        int i = 1/0;
        return "新增支付成功";
    }
    public String confirmAddPay(TblPay bean){
        System.out.println("pay confirm");
        return "confirm 支付成功";

    }
    private static java.util.Map<String,Integer> maps = new HashMap<>();

    /**
     * 逆sql
     * @param bean
     * @return
     */
    public String cancelAddPay(TblPay bean){
        redisTemplate.delete("pay");
        System.out.println("pay cancel");
        return "取消支付成功";
    }
}

标签:事务,pay,模型,springframework,annotation,org,import,com,TCC
来源: https://www.cnblogs.com/zheaven/p/15560278.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有