zoukankan      html  css  js  c++  java
  • springcloud分布式事务LCN实现

    1  LCN介绍

    利用事务管理器,统一协调各个本地事务,实现事务的一致性。

    特性:

    1、一致性,通过TxManager协调控制与事务补偿机制确保数据一致性

    2、易用性,仅需要在业务方法上添加@TxTransaction注解即可

    3、高可用,项目模块不仅可高可用部署,事务协调器也可集群化部署

    4、扩展性,支持各种RPC框架扩展,支持通讯协议与事务模式扩展

    官方文档:https://www.txlcn.org/zh-cn/docs/preface.html

    源码参考:https://gitee.com/wangliang1991/tx-lcn/tree/4.1.0/

    2  tx-manager资源管理器改造

    下载资源管理器代码 tx-manager,进行改造,可自行调整注册中心和redis集成等。

    修改配置application.properties

    调整端口、注册中心配置,redis配置

    tx-manager.zip

    3  分布式事务集成使用

    3.1 微服务service-1改造

    3.1.1  添加pom依赖配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <!--分布式事务配置-->
        <dependency>
            <groupId>com.codingapi</groupId>
            <artifactId>transaction-springcloud</artifactId>
            <version>4.1.0</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.codingapi</groupId>
            <artifactId>tx-plugins-db</artifactId>
            <version>4.1.0</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--分布式事务配置-->

      

    3.1.2  添加tx-manger地址配置

    新增tx.properties

    url=http://127.0.0.1:9000/tx/manager/

    3.1.3 添加测试接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @RestController
        @RequestMapping("/test")
        public class TestController {
            private static Logger LOGGER = LoggerFactory.getLogger(TestController.class);
            @Autowired
            private IDemoService demoService;
            @PostMapping(value = "/save", produces = "application/json;charset=utf-8")
            @ResponseBody
            public int save(){
                return demoService.save();
            }
        }

      

    1
    2
    3
    4
    public interface IDemoService {
        List<Test> list();
        int save();
    }

      

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    @Service
        public class DemoServiceImpl implements IDemoService /*,ITxTransaction*/ {
            @Autowired
            private ITestDao testDao;
            private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class);
            @Override
            public List<Test> list() {
                return testDao.findAll();
            }
            /**
         *  @TxTransaction(isStart = false) //true:事务发起方 false: 事务参与方 ,默认为参与方
         *   参与方添加注解@TxTransaction或者实现接口ITxTransaction效果一样。
         * @return
         */
        @Override
        @TxTransaction
        @Transactional
        public int save() {
                int rs1 = testDao.save("test-service-2");
                return rs1;
            }
        }

      

    1
    2
    3
    4
    5
    6
    7
    @Mapper
        public interface ITestDao {
            @Select("SELECT * FROM t_test")
            List<Test> findAll();
            @Insert("INSERT INTO t_test(name) VALUES(#{name})")
            int save(@Param("name") String name);
        }

      

    3.2  微服务service-2改造

    3.2.1  添加pom依赖配置

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    <!--分布式事务配置-->
        <dependency>
            <groupId>com.codingapi</groupId>
            <artifactId>transaction-springcloud</artifactId>
            <version>4.1.0</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>com.codingapi</groupId>
            <artifactId>tx-plugins-db</artifactId>
            <version>4.1.0</version>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>*</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <!--分布式事务配置-->

      

    3.2.2  添加tx-manger地址配置

    新增tx.properties

    url=http://127.0.0.1:9000/tx/manager/

    3.2.3 添加测试接口

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    @RestController
        @RequestMapping("/test")
        public class TestController {
            private static Logger LOGGER = LoggerFactory.getLogger(TestController.class);
            @Autowired
            private IDemoService demoService;
            @PostMapping(value = "/save", produces = "application/json;charset=utf-8")
            @ResponseBody
            public int save(){
                return demoService.save();
            }
        }

      

    1
    2
    3
    4
    public interface IDemoService {
        List<Test> list();
        int save();
        }

      

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    @Service
        public class DemoServiceImpl implements IDemoService {
            @Autowired
            private ServiceFeignClient serviceFeignClient;
            @Autowired
            private ITestDao testDao;
            private static final Logger logger = LoggerFactory.getLogger(DemoServiceImpl.class);
            @Override
            public List<Test> list() {
                return testDao.findAll();
            }
     
            @Override
            @TxTransaction(isStart = true//true:事务发起方 false:事务参与方
            @Transactional
            public int save() {
                int rs1 = testDao.save("test-service-2");
                int rs2 = serviceFeignClient.save();
                int v = 100/0;
                return rs1+rs2;
            }
        }

      

    1
    2
    3
    4
    5
    6
    7
    @Mapper
        public interface ITestDao {
            @Select("SELECT * FROM t_test")
            List<Test> findAll();
            @Insert("INSERT INTO t_test(name) VALUES(#{name})")
            int save(@Param("name") String name);
        }

      

    3.2.4 添加feign配置

    1
    2
    3
    4
    5
    6
    @FeignClient(name = "service-1")
      public interface ServiceFeignClient {
          @PostMapping(value = "/test/save")
          @ResponseBody
          int save();
      }
    配置文件:
    #######################################txmanager-start#################################################
    #\u670D\u52A1\u7AEF\u53E3
    server.port=9000
    #tx-manager\u4E0D\u5F97\u4FEE\u6539
    spring.application.name=tx-manager

    # \u5F00\u542FAPI\u6CE8\u518C\u529F\u80FD \u672C\u5730dev\u9700\u8981\u5173\u95ED \u5426\u5219\u4F1A\u62A5Value is too long
    tsf.swagger.enabled=false
    logging.file=/supplier-logs/${spring.application.name}.log

    spring.mvc.static-path-pattern=/**
    spring.resources.static-locations=classpath:/static/
    #######################################txmanager-end#################################################

    #zookeeper\u5730\u5740
    #spring.cloud.zookeeper.connect-string=127.0.0.1:2181
    #spring.cloud.zookeeper.discovery.preferIpAddress = true

    #eureka \u5730\u5740
    eureka.client.service-url.defaultZone=http://127.0.0.1:65/eureka/
    eureka.instance.prefer-ip-address=true

    #######################################redis-start#################################################
    #redis \u914D\u7F6E\u6587\u4EF6\uFF0C\u6839\u636E\u60C5\u51B5\u9009\u62E9\u96C6\u7FA4\u6216\u8005\u5355\u673A\u6A21\u5F0F

    ##redis \u96C6\u7FA4\u73AF\u5883\u914D\u7F6E
    ##redis cluster
    #spring.redis.cluster.nodes=127.0.0.1:7001,127.0.0.1:7002,127.0.0.1:7003
    #spring.redis.cluster.commandTimeout=5000

    #redis
    spring.redis.hostName=192.168.1.1
    spring.redis.port=7000
    # REDIS (RedisProperties)
    # Redis\u6570\u636E\u5E93\u7D22\u5F15\uFF08\u9ED8\u8BA4\u4E3A0\uFF09
    spring.redis.database=0
    # Redis\u670D\u52A1\u5668\u8FDE\u63A5\u5BC6\u7801\uFF08\u9ED8\u8BA4\u4E3A\u7A7A\uFF09
    spring.redis.password=1234567
    # \u8FDE\u63A5\u6C60\u6700\u5927\u8FDE\u63A5\u6570\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09
    # \u8FDE\u63A5\u8D85\u65F6\u65F6\u95F4\uFF08\u6BEB\u79D2\uFF09
    spring.redis.timeout=5000
    spring.redis.pool.max-active= 3000
    # \u8FDE\u63A5\u6C60\u6700\u5927\u963B\u585E\u7B49\u5F85\u65F6\u95F4\uFF08\u4F7F\u7528\u8D1F\u503C\u8868\u793A\u6CA1\u6709\u9650\u5236\uFF09
    spring.redis.pool.max-wait=5000
    # \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5927\u7A7A\u95F2\u8FDE\u63A5
    spring.redis.pool.max-idle=1000
    # \u8FDE\u63A5\u6C60\u4E2D\u7684\u6700\u5C0F\u7A7A\u95F2\u8FDE\u63A5
    spring.redis.pool.min-idle=200
    spring.session.store-type=redis
    #redis\u914D\u7F6E*********************
    #####################################redis-end###################################################




    #######################################LCN-start#################################################
    #\u4E1A\u52A1\u6A21\u5757\u4E0ETxManager\u4E4B\u95F4\u901A\u8BAF\u7684\u6700\u5927\u7B49\u5F85\u65F6\u95F4\uFF08\u5355\u4F4D\uFF1A\u79D2\uFF09
    #\u901A\u8BAF\u65F6\u95F4\u662F\u6307\uFF1A\u53D1\u8D77\u65B9\u4E0E\u54CD\u5E94\u65B9\u4E4B\u95F4\u5B8C\u6210\u4E00\u6B21\u7684\u901A\u8BAF\u65F6\u95F4\u3002
    #\u8BE5\u5B57\u6BB5\u4EE3\u8868\u7684\u662FTx-Client\u6A21\u5757\u4E0ETxManager\u6A21\u5757\u4E4B\u95F4\u7684\u6700\u5927\u901A\u8BAF\u65F6\u95F4\uFF0C\u8D85\u8FC7\u8BE5\u65F6\u95F4\u672A\u54CD\u5E94\u672C\u6B21\u8BF7\u6C42\u5931\u8D25\u3002
    tm.transaction.netty.delaytime = 5

    #\u4E1A\u52A1\u6A21\u5757\u4E0ETxManager\u4E4B\u95F4\u901A\u8BAF\u7684\u5FC3\u8DF3\u65F6\u95F4\uFF08\u5355\u4F4D\uFF1A\u79D2\uFF09
    tm.transaction.netty.hearttime = 15

    #\u5B58\u50A8\u5230redis\u4E0B\u7684\u6570\u636E\u6700\u5927\u4FDD\u5B58\u65F6\u95F4\uFF08\u5355\u4F4D\uFF1A\u79D2\uFF09
    #\u8BE5\u5B57\u6BB5\u4EC5\u4EE3\u8868\u7684\u4E8B\u52A1\u6A21\u5757\u6570\u636E\u7684\u6700\u5927\u4FDD\u5B58\u65F6\u95F4\uFF0C\u8865\u507F\u6570\u636E\u4F1A\u6C38\u4E45\u4FDD\u5B58\u3002
    tm.redis.savemaxtime=30

    #socket server Socket\u5BF9\u5916\u670D\u52A1\u7AEF\u53E3
    #TxManager\u7684LCN\u534F\u8BAE\u7684\u7AEF\u53E3
    tm.socket.port=9999

    #\u6700\u5927socket\u8FDE\u63A5\u6570
    #TxManager\u6700\u5927\u5141\u8BB8\u7684\u5EFA\u7ACB\u8FDE\u63A5\u6570\u91CF
    tm.socket.maxconnection=100

    #\u4E8B\u52A1\u81EA\u52A8\u8865\u507F (true:\u5F00\u542F\uFF0Cfalse:\u5173\u95ED)
    # \u8BF4\u660E\uFF1A
    # \u5F00\u542F\u81EA\u52A8\u8865\u507F\u4EE5\u540E\uFF0C\u5FC5\u987B\u8981\u914D\u7F6E tm.compensate.notifyUrl \u5730\u5740\uFF0C\u4EC5\u5F53tm.compensate.notifyUrl \u5728\u8BF7\u6C42\u8865\u507F\u786E\u8BA4\u65F6\u8FD4\u56DEsuccess\u6216\u8005SUCCESS\u65F6\uFF0C\u624D\u4F1A\u6267\u884C\u81EA\u52A8\u8865\u507F\uFF0C\u5426\u5219\u4E0D\u4F1A\u81EA\u52A8\u8865\u507F\u3002
    # \u5173\u95ED\u81EA\u52A8\u8865\u507F\uFF0C\u5F53\u51FA\u73B0\u6570\u636E\u65F6\u4E5F\u4F1A tm.compensate.notifyUrl \u5730\u5740\u3002
    # \u5F53tm.compensate.notifyUrl \u65E0\u6548\u65F6\uFF0C\u4E0D\u5F71\u54CDTxManager\u8FD0\u884C\uFF0C\u4EC5\u4F1A\u5F71\u54CD\u81EA\u52A8\u8865\u507F\u3002
    tm.compensate.auto=false

    #\u4E8B\u52A1\u8865\u507F\u8BB0\u5F55\u56DE\u8C03\u5730\u5740(rest api \u5730\u5740\uFF0Cpost json\u683C\u5F0F)
    #\u8BF7\u6C42\u8865\u507F\u662F\u5728\u5F00\u542F\u81EA\u52A8\u8865\u507F\u65F6\u624D\u4F1A\u8BF7\u6C42\u7684\u5730\u5740\u3002\u8BF7\u6C42\u5206\u4E3A\u4E24\u79CD\uFF1A1.\u8865\u507F\u51B3\u7B56\uFF0C2.\u8865\u507F\u7ED3\u679C\u901A\u77E5\uFF0C\u53EF\u901A\u8FC7\u901A\u8FC7action\u53C2\u6570\u533A\u5206compensate\u4E3A\u8865\u507F\u8BF7\u6C42\u3001notify\u4E3A\u8865\u507F\u901A\u77E5\u3002
    #*\u6CE8\u610F\u5F53\u8BF7\u6C42\u8865\u507F\u51B3\u7B56\u65F6\uFF0C\u9700\u8981\u8865\u507F\u670D\u52A1\u8FD4\u56DE"SUCCESS"\u5B57\u7B26\u4E32\u4EE5\u540E\u624D\u53EF\u4EE5\u6267\u884C\u81EA\u52A8\u8865\u507F\u3002
    #\u8BF7\u6C42\u8865\u507F\u7ED3\u679C\u901A\u77E5\u5219\u53EA\u9700\u8981\u63A5\u53D7\u901A\u77E5\u5373\u53EF\u3002
    #\u8BF7\u6C42\u8865\u507F\u7684\u6837\u4F8B\u6570\u636E\u683C\u5F0F:
    #{"groupId":"TtQxTwJP","action":"compensate","json":"{\"address\":\"133.133.5.100:8081\",\"className\":\"com.example.demo.service.impl.DemoServiceImpl\",\"currentTime\":1511356150413,\"data\":\"C5IBLWNvbS5leGFtcGxlLmRlbW8uc2VydmljZS5pbXBsLkRlbW9TZXJ2aWNlSW1wbAwSBHNhdmUbehBqYXZhLmxhbmcuT2JqZWN0GAAQARwjeg9qYXZhLmxhbmcuQ2xhc3MYABABJCo/cHVibGljIGludCBjb20uZXhhbXBsZS5kZW1vLnNlcnZpY2UuaW1wbC5EZW1vU2VydmljZUltcGwuc2F2ZSgp\",\"groupId\":\"TtQxTwJP\",\"methodStr\":\"public int com.example.demo.service.impl.DemoServiceImpl.save()\",\"model\":\"demo1\",\"state\":0,\"time\":36,\"txGroup\":{\"groupId\":\"TtQxTwJP\",\"hasOver\":1,\"isCompensate\":0,\"list\":[{\"address\":\"133.133.5.100:8899\",\"isCompensate\":0,\"isGroup\":0,\"kid\":\"wnlEJoSl\",\"methodStr\":\"public int com.example.demo.service.impl.DemoServiceImpl.save()\",\"model\":\"demo2\",\"modelIpAddress\":\"133.133.5.100:8082\",\"channelAddress\":\"/133.133.5.100:64153\",\"notify\":1,\"uniqueKey\":\"bc13881a5d2ab2ace89ae5d34d608447\"}],\"nowTime\":0,\"startTime\":1511356150379,\"state\":1},\"uniqueKey\":\"be6eea31e382f1f0878d07cef319e4d7\"}"}
    #\u8BF7\u6C42\u8865\u507F\u7684\u8FD4\u56DE\u6570\u636E\u6837\u4F8B\u6570\u636E\u683C\u5F0F:
    #SUCCESS
    #\u8BF7\u6C42\u8865\u507F\u7ED3\u679C\u901A\u77E5\u7684\u6837\u4F8B\u6570\u636E\u683C\u5F0F:
    #{"resState":true,"groupId":"TtQxTwJP","action":"notify"}
    tm.compensate.notifyUrl=http://ip:port/path

    #\u8865\u507F\u5931\u8D25\uFF0C\u518D\u6B21\u5C1D\u8BD5\u95F4\u9694\uFF08\u79D2\uFF09\uFF0C\u6700\u5927\u5C1D\u8BD5\u6B21\u65703\u6B21\uFF0C\u5F53\u8D85\u8FC73\u6B21\u5373\u4E3A\u8865\u507F\u5931\u8D25,\u5931\u8D25\u7684\u6570\u636E\u4F9D\u65E7\u8FD8\u4F1A\u5B58\u5728TxManager\u4E0B\u3002
    tm.compensate.tryTime=30

    #\u5404\u4E8B\u52A1\u6A21\u5757\u81EA\u52A8\u8865\u507F\u7684\u65F6\u95F4\u4E0A\u9650(\u6BEB\u79D2)
    #\u6307\u7684\u662F\u6A21\u5757\u6267\u884C\u81EA\u52A8\u8D85\u65F6\u7684\u6700\u5927\u65F6\u95F4\uFF0C\u8BE5\u6700\u5927\u65F6\u95F4\u82E5\u8FC7\u6BB5\u4F1A\u5BFC\u81F4\u4E8B\u52A1\u673A\u5236\u5F02\u5E38\uFF0C\u8BE5\u65F6\u95F4\u5FC5\u987B\u8981\u6A21\u5757\u4E4B\u95F4\u901A\u8BAF\u7684\u6700\u5927\u8D85\u8FC7\u65F6\u95F4\u3002
    #\u4F8B\u5982\uFF0C\u82E5\u6A21\u5757A\u4E0E\u6A21\u5757B\uFF0C\u8BF7\u6C42\u8D85\u65F6\u7684\u6700\u5927\u65F6\u95F4\u662F5\u79D2\uFF0C\u5219\u5EFA\u8BAE\u6539\u65F6\u95F4\u81F3\u5C11\u5927\u4E8E5\u79D2\u3002
    tm.compensate.maxWaitTime=5000
    #######################################LCN-end#################################################


    logging.level.com.codingapi=debug



    mpmt.sm4.enable=false
    mpmt.mongodb.enabled=false

      

    转自https://www.cnblogs.com/brant/p/12547183.html

  • 相关阅读:
    异步编程与scrapy
    统计学 李航读书笔记
    算法模型手写
    《剑指offer》面试题的Python实现
    numpy 中文手册
    django部署
    Django ORM中使用update_or_create功能再解
    RabbitMQ(七)心跳控制 -- heartbeat
    重写__eq__函数——对象list中使用in index()——获得list中不同属性对象个数
    Python机器学习及分析工具:Scikit-learn篇
  • 原文地址:https://www.cnblogs.com/javalinux/p/14265446.html
Copyright © 2011-2022 走看看