Java中SpringBoot的TCC事務(wù)詳解
Spring Boot 中的 TCC 事務(wù)
在分布式系統(tǒng)中,事務(wù)一直是一個(gè)棘手的問(wèn)題。傳統(tǒng)的 ACID 事務(wù)無(wú)法滿足分布式系統(tǒng)的需求,因?yàn)樗鼈冃枰獜?qiáng)一致性、單點(diǎn)故障和網(wǎng)絡(luò)延遲等問(wèn)題。
近年來(lái),隨著微服務(wù)架構(gòu)的普及,TCC 事務(wù)成為了一種非常流行的分布式事務(wù)解決方案。在 Spring Boot 中,我們可以很容易地使用 TCC 事務(wù)來(lái)管理分布式事務(wù)。
本文將介紹 TCC 事務(wù)的概念和原理,并說(shuō)明如何在 Spring Boot 中使用它們。
TCC 事務(wù)的概念和原理
TCC 事務(wù)是一種基于補(bǔ)償事務(wù)的分布式事務(wù)解決方案。它由 Try、Confirm 和 Cancel 三個(gè)階段組成,每個(gè)階段都是一個(gè)本地事務(wù)。
在 TCC 事務(wù)中,Try 階段會(huì)嘗試執(zhí)行業(yè)務(wù)操作,并為 Confirm 和 Cancel 階段做好準(zhǔn)備。如果 Try 階段執(zhí)行成功,則 Confirm 階段會(huì)提交事務(wù),否則 Cancel 階段會(huì)回滾事務(wù)。
舉個(gè)例子,假設(shè)我們要在兩個(gè)賬戶之間轉(zhuǎn)賬。在 TCC 事務(wù)中,我們可以這樣實(shí)現(xiàn):
- Try 階段:從賬戶 A 中扣減金額,同時(shí)向賬戶 B 中增加金額。
- Confirm 階段:提交 Try 階段的操作,將金額轉(zhuǎn)移成功。
- Cancel 階段:回滾 Try 階段的操作,將金額轉(zhuǎn)移失敗。
在 TCC 事務(wù)中,如果 Confirm 階段執(zhí)行成功,則整個(gè)事務(wù)就提交成功了;如果 Confirm 階段執(zhí)行失敗,則整個(gè)事務(wù)就會(huì)回滾。
Spring Boot 中的 TCC 事務(wù)實(shí)現(xiàn)
在 Spring Boot 中,我們可以使用 Seata 來(lái)實(shí)現(xiàn) TCC 事務(wù)。Seata 是一款開(kāi)源的分布式事務(wù)解決方案,可以幫助我們實(shí)現(xiàn)分布式事務(wù)的管理和控制。
以下是一個(gè)簡(jiǎn)單的 Spring Boot + Seata TCC 事務(wù)示例,用于轉(zhuǎn)賬操作:
1.定義 TCC 服務(wù)接口
public interface AccountService { @TccTransaction void transfer(String fromAccountId, String toAccountId, BigDecimal amount); boolean tryTransfer(String fromAccountId, String toAccountId, BigDecimal amount); void confirmTransfer(String fromAccountId, String toAccountId, BigDecimal amount); void cancelTransfer(String fromAccountId, String toAccountId, BigDecimal amount); }
在這個(gè)示例中,我們定義了一個(gè) AccountService 接口,其中包含了 transfer、tryTransfer、confirmTransfer 和 cancelTransfer 四個(gè)方法。
其中,transfer 方法是一個(gè) TCC 事務(wù)方法,tryTransfer、confirmTransfer 和 cancelTransfer 方法是其對(duì)應(yīng)的 Try、Confirm 和 Cancel 方法。
2.實(shí)現(xiàn) TCC 服務(wù)接口
@Service public class AccountServiceImpl implements AccountService { @Resource private AccountMapper accountMapper; @Override public boolean tryTransfer(String fromAccountId, String toAccountId, BigDecimal amount) { Account fromAccount = accountMapper.selectById(fromAccountId); if (fromAccount.getBalance().compareTo(amount) < 0) { throw new RuntimeException("Insufficient balance"); } accountMapper.updateBalance(fromAccountId, fromAccount.getBalance().subtract(amount)); return true; } @Override public void confirmTransfer(String fromAccountId, String toAccountId, BigDecimal amount) { Account toAccount = accountMapper.selectById(toAccountId); accountMapper.updateBalance(toAccountId, toAccount.getBalance().add(amount)); } @Override public void cancelTransfer(String fromAccountId, String toAccountId, BigDecimal amount) { Account fromAccount = accountMapper.selectById(fromAccountId); accountMapper.updateBalance(fromAccountId, fromAccount.getBalance().add(amount)); } @Override public void transfer(String fromAccountId, String toAccountId, BigDecimal amount) { boolean result = tryTransfer(fromAccountId, toAccountId, amount); if (!result) { throw new RuntimeException("Try transfer failed"); } } }
在這個(gè)示例中,我們實(shí)現(xiàn)了AccountService 接口,并覆蓋了 tryTransfer、confirmTransfer 和 cancelTransfer 三個(gè)方法。
其中,tryTransfer 方法會(huì)嘗試扣減賬戶余額并返回 true,如果余額不足則會(huì)拋出異常;
confirmTransfer 方法會(huì)向目標(biāo)賬戶增加金額;
cancelTransfer 方法會(huì)將扣減的金額恢復(fù)到原賬戶中。
transfer 方法是 TCC 事務(wù)方法,它會(huì)在 tryTransfer 方法執(zhí)行成功后提交事務(wù),否則回滾事務(wù)。
3.配置 Seata 數(shù)據(jù)源
在 Spring Boot 中,我們需要配置 Seata 數(shù)據(jù)源來(lái)支持 TCC 事務(wù)。以下是一個(gè)基本的 Seata 數(shù)據(jù)源配置:
spring: datasource: url: jdbc:mysql://localhost:3306/seata username: root password: root driver-class-name: com.mysql.jdbc.Driver cloud: alibaba: seata: tx-service-group: my_test_tx_group config: type: nacos serverAddr: localhost:8848 namespace: public config-mode: file
在這個(gè)示例中,我們使用了 Seata 的 Nacos 配置中心來(lái)存儲(chǔ)配置信息。
- tx-service-group 屬性指定了 Seata 事務(wù)組的名稱
- config-type 屬性指定了配置中心的類型
- serverAddr 屬性指定了配置中心的地址
- namespace 屬性指定了配置中心的命名空間
- config-mode 屬性指定了配置中心的模式。
4.配置 Seata 代理和 TCC 事務(wù)
seata: enabled: true application-id: account-service tx-service-group: my_test_tx_group service: vgroup-mapping: account-service: my_test_tx_group group-list: my_test_tx_group config: type: nacos serverAddr: localhost:8848 namespace: public config-mode: file registry: type: nacos serverAddr: localhost:8848 namespace: public tm: commit_retry_count: 5 rollback_retry_count: 5 undo: data-validation: true log-table: undo_log
在這個(gè)示例中,我們配置了 Seata 的代理和 TCC 事務(wù)。
- enabled 屬性指定了是否啟用 Seata
- application-id 屬性指定了當(dāng)前應(yīng)用的 ID
- tx-service-group 屬性指定了
- Seata 事務(wù)組的名稱
- service 屬性指定了應(yīng)用和事務(wù)組之間的映射關(guān)系
- config 屬性指定了配置中心的類型和地址
- registry 屬性指定了注冊(cè)中心的類型和地址
- tm 屬性指定了事務(wù)管理器的參數(shù)
- undo 屬性指定了事務(wù)撤銷的參數(shù)。
5.配置 Spring Boot 應(yīng)用
最后,我們需要在 Spring Boot 應(yīng)用中配置 Seata 數(shù)據(jù)源和 TCC 事務(wù)。以下是一個(gè)基本的 Spring Boot 配置文件:
spring: datasource: url: jdbc:mysql://localhost:3306/account username: root password: root driver-class-name: com.mysql.jdbc.Driver cloud: alibaba: seata: tx-service-group: my_test_tx_group config: type: nacos serverAddr: localhost:8848 namespace: public config-mode: file proxy: table: undo_log log-store: db
在這個(gè)示例中,我們配置了 Spring Boot 應(yīng)用的數(shù)據(jù)源和 Seata 的 TCC 事務(wù)代理。
- tx-service-group 屬性指定了 Seata 事務(wù)組的名稱
- config 屬性指定了配置中心的類型和地址
- proxy 屬性指定了事務(wù)代理的參數(shù)。
總結(jié)
TCC 事務(wù)是一種基于補(bǔ)償事務(wù)的分布式事務(wù)解決方案,可以幫助我們解決分布式事務(wù)的問(wèn)題。
在 Spring Boot 中,我們可以使用 Seata 來(lái)實(shí)現(xiàn) TCC 事務(wù),并利用其強(qiáng)大的功能來(lái)管理和控制分布式事務(wù)。
到此這篇關(guān)于Java中SpringBoot的TCC事務(wù)詳解的文章就介紹到這了,更多相關(guān)SpringBoot的TCC事務(wù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
反射機(jī)制:getDeclaredField和getField的區(qū)別說(shuō)明
這篇文章主要介紹了反射機(jī)制:getDeclaredField和getField的區(qū)別說(shuō)明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-06-06泛型的類型擦除后fastjson反序列化時(shí)如何還原詳解
這篇文章主要為大家介紹了泛型的類型擦除后fastjson反序列化時(shí)如何還原詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-11-11使用Spring Initializr創(chuàng)建Spring Boot項(xiàng)目沒(méi)有JDK1.8的解決辦法
很久沒(méi)創(chuàng)建springboot項(xiàng)目,今天使用idea的Spring Initializr 創(chuàng)建 Spring Boot項(xiàng)目時(shí),發(fā)現(xiàn)java版本里,無(wú)法選擇jdk1.8,只有17、21、22,所以本文介紹了使用Spring Initializr創(chuàng)建Spring Boot項(xiàng)目沒(méi)有JDK1.8的解決辦法,需要的朋友可以參考下2024-06-06SpringBoot實(shí)現(xiàn)優(yōu)雅停機(jī)的多種方式
優(yōu)雅停機(jī)(Graceful Shutdown)在現(xiàn)代微服務(wù)架構(gòu)中是非常重要的,它幫助我們確保在應(yīng)用程序停止時(shí),不會(huì)中斷正在進(jìn)行的請(qǐng)求或?qū)е聰?shù)據(jù)丟失,讓我們以通俗易懂的方式來(lái)講解這個(gè)概念以及如何在 Spring Boot 中實(shí)現(xiàn)它,需要的朋友可以參考下2025-01-01Java如何實(shí)現(xiàn)將類文件打包為jar包
這篇文章主要介紹了Java如何實(shí)現(xiàn)將類文件打包為jar包,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-06-06