springCloud集成分佈式事務LCN 5.0.2 (一)

前言

以前我寫過一個基於springboot1.5.6+lcn4.1.0 的集成文章https://segmentfault.com/a/11... .最近新項目使用了springboot2.1.3,基於目前更新的lcn5.0.2分析了一波源碼。在此作一些記錄(ps:若是對分佈式事務不是很瞭解,能夠先看下我上面貼的連接,本文基於有基礎的狀況去分析的)mysql

TX-LCN的3種模式

LCN5.0.2有3種模式,分別是LCN模式,TCC模式,TXC模式redis

  • LCN模式:spring

    LCN模式是經過代理Connection的方式實現對本地事務的操做,而後在由TxManager統一協調控制事務。當本地事務提交回滾或者關閉鏈接時將會執行假操做,該代理的鏈接將由LCN鏈接池管理。
    該模式的特色:sql

    - 該模式對代碼的嵌入性爲低。
    - 該模式僅限於本地存在鏈接對象且可經過鏈接對象控制事務的模塊。
    - 該模式下的事務提交與回滾是由本地事務方控制,對於數據一致性上有較高的保障。
    - 該模式缺陷在於代理的鏈接須要隨事務發起方一共釋放鏈接,增長了鏈接佔用的時間。
  • TCC模式:數據庫

    TCC事務機制相對於傳統事務機制(X/Open XA Two-Phase-Commit),其特徵在於它不依賴資源管理器(RM)對XA的支持,而是經過對(由業務系統提供的)業務邏輯的調度來實現分佈式事務。主要由三步操做,Try: 嘗試執行業務、 Confirm:確認執行業務、 Cancel: 取消執行業務。segmentfault

    該模式的特色:api

    - 該模式對代碼的嵌入性高,要求每一個業務須要寫三種步驟的操做。
    - 該模式對有無本地事務控制均可以支持使用面廣。
    - 數據一致性控制幾乎徹底由開發者控制,對業務開發難度要求高。
  • TXC模式:
    TXC模式命名來源於淘寶,實現原理是在執行SQL以前,先查詢SQL的影響數據,而後保存執行的SQL快走信息和建立鎖。當須要回滾的時候就採用這些記錄數據回滾數據庫,目前鎖實現依賴redis分佈式鎖控制。
    該模式的特色:springboot

    - 該模式一樣對代碼的嵌入性低。
    - 該模式僅限於對支持SQL方式的模塊支持。
    - 該模式因爲每次執行SQL以前須要先查詢影響數據,所以相比LCN模式消耗資源與時間要多。
    - 該模式不會佔用數據庫的鏈接資源。
LCN原理

這裏引用一下官網的原理圖:
圖片描述app

總的來講,核心步驟就是建立事務組,假如事務組,通知事務組分佈式

建立事務組

  • 是指在事務發起方開始執行業務代碼以前先調用TxManager建立事務組對象,而後拿到事務標示GroupId的過程。

加入事務組

  • 添加事務組是指參與方在執行完業務方法之後,將該模塊的事務信息通知給TxManager的操做

通知事務組

  • 是指在發起方執行完業務代碼之後,將發起方執行結果狀態通知給TxManager,TxManager將根據事務最終狀態和事務組的信息來通知相應的參與模塊提交或回滾事務,並返回結果給事務發起方。
集成springCloud
(ps:我這裏使用的springboot版本是2.1.3)
<!----pom.xml 今天是2019.4.24 最新版本是5.0.2 --->
<properties>
    <codingapi.txlcn.version>5.0.2.RELEASE</codingapi.txlcn.version>
</properties>

<dependency>
        <groupId>com.codingapi.txlcn</groupId>
        <artifactId>txlcn-tc</artifactId>
        <version>${codingapi.txlcn.version}</version>
    </dependency>

    <dependency>
        <groupId>com.codingapi.txlcn</groupId>
        <artifactId>txlcn-tm</artifactId>
        <version>${codingapi.txlcn.version}</version>
    </dependency>

    <dependency>
        <groupId>com.codingapi.txlcn</groupId>
        <artifactId>txlcn-txmsg-netty</artifactId>
        <version>${codingapi.txlcn.version}</version>
    </dependency>

A啓動類上加註解:@EnableDistributedTransaction 代表這是一個txmanager的client

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableDistributedTransaction
@MapperScan("cn.iamcrawler.crawlergoddess.mapper")
@ComponentScan("cn.iamcrawler.crawlergoddess,cn.iamcrawler.crawler_common.feign")
public class CrawlerGoddessApplication {

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

yml(ps 我把密碼隱藏了,數據庫我用的是postgresql,lcn默認的是mysql):

server:
  port: 9993

spring:
  datasource:
    url: jdbc:postgresql://www.iamcrawler.cn:5432/mft?characterEncoding=utf8&useUnicode=true&useSSL=false&serverTimezone=UTC
    username: postgres
    password: **
    driver-class-name:  org.postgresql.Driver
  redis:
    host: www.iamcrawler.cn
    port: 6379
    password: **
    database: 0
  application:
    name: crawler-goddess
  rabbitmq:
    host: www.iamcrawler.cn
    port: 5672
    username: liuliang
    password: **
  jpa:
    properties:
      hibernate:
        jdbc:
          lob:
            non_contextual_creation: true
    database-platform: org.hibernate.dialect.PostgreSQL9Dialect
#  aop:
#    proxy-target-class: true

eureka:
  client:
    service-url:
      defaultZone: http://localhost:9990/eureka/

init-db: true


tx-lcn:
  client:
    manager-address: 127.0.0.1:8070
  logger:
    enabled: true
    driver-class-name: ${spring.datasource.driver-class-name}
    jdbc-url: jdbc:postgresql://www.iamcrawler.cn:5432/mft?characterEncoding=UTF-8
    username: ${spring.datasource.username}
    password: ${spring.datasource.password}

logging:
  level:
    com:
      codingapi: debug

A模塊代碼示例:

@Transactional
    @LcnTransaction//代表使用lcn模式
    public void testLcn(){
        PgTestUser testUser = new PgTestUser();
        testUser.setAge(1);
        testUser.setName("liuliang");
        testUser.setRemark("要買東西");
        testUser.setSalary(new BigDecimal(10));
        this.save(testUser);
        PgOrder order = new PgOrder();
        order.setAmount(new BigDecimal(10));
        order.setItemName("小視頻");
        kindnessFeign.insertOne(order);
        logger.info("===============");
        throw new RuntimeException("");

//        logger.info("插入完畢...事務提交!");

    }

B模塊代碼示例

@LcnTransaction
    @Transactional
    public Boolean insertOne(PgOrder pgOrder) {

        RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
        HttpServletRequest request = requestAttributes == null ? null : ((ServletRequestAttributes) requestAttributes).getRequest();
//        String groupId = TracingContext.tracing().groupId();
//        String applicationId = Transactions.getApplicationId();

        boolean save = pgOrderService.save(pgOrder);
        return save;
    }

而後調用便可,LCN5.0.2的lcn模式也4.1.0的TX模式很相似,就是不用標記isStart=true了,而且還支持TCC模式和TXC模式,TCC模式能夠控制多個鏈接,好比A使用mysql,B使用Redis,C使用Mongodb,D模塊使用postgresql,可使用TCC模式。可是TCC模式須要有注意的地方。下一篇文章將結合源碼仔細說明

相關文章
相關標籤/搜索