日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > 單片機 > 架構師社區(qū)
[導讀]? ? ? 一、背景 有一定分布式開發(fā)經(jīng)驗的朋友都知道,產(chǎn)品/項目/系統(tǒng)最初為了能夠快速迭代上線,往往不太注重產(chǎn)品/項目/系統(tǒng)的高可靠性、高性能與高擴展性,采用單體應用和單實例數(shù)據(jù)庫的架構方式快速迭代開發(fā);當產(chǎn)品/項目/系統(tǒng)做到一定規(guī)模的時候,原有的系

【分布式事務】tcc-transaction分布式TCC型事務框架搭建與實戰(zhàn)案例(基于Dubbo/Dubbox)

     

一、背景


有一定分布式開發(fā)經(jīng)驗的朋友都知道,產(chǎn)品/項目/系統(tǒng)最初為了能夠快速迭代上線,往往不太注重產(chǎn)品/項目/系統(tǒng)的高可靠性、高性能與高擴展性,采用單體應用和單實例數(shù)據(jù)庫的架構方式快速迭代開發(fā);當產(chǎn)品/項目/系統(tǒng)做到一定規(guī)模的時候,原有的系統(tǒng)架構則不足以支撐義務發(fā)展需要,往往相同的業(yè)務則需要重復寫很多次,導致代碼大量冗余,難以維護和擴展,這時不得不對原有產(chǎn)品/項目/系統(tǒng)進行拆分,引入分布式的系統(tǒng)架構;而對原有產(chǎn)品/項目/系統(tǒng)進行拆分的過程中,對于業(yè)務和數(shù)據(jù)的拆分和遷移則成為了最為棘手的問題,尤其是在原有業(yè)務不能下線,拆分后的業(yè)務同時上線的場景下這種問題更加突出;項目拆分后,業(yè)務被拆分為多個獨立的子業(yè)務分散到多個子系統(tǒng)中,而原有的單一數(shù)據(jù)庫則被拆分到多個數(shù)據(jù)庫中,拆分后的數(shù)據(jù)庫則同樣又面臨著讓人頭疼的分布式事務的問題。


本文就針對項目拆分后數(shù)據(jù)庫的分布式事務問題,基于tcc-transaction分布式TCC型事務進行框架的搭建,同時引入相關的實戰(zhàn)案例,來解決讓人頭疼的分布式事務問題。


二、tcc-transaction框架介紹


介紹:tcc-transaction是開源的TCC補償性分布式事務框架,Git地址:https://github.com/changmingxie/tcc-transaction

TCC為Try、Confirm、Cancel的縮寫:try階段預留資源嘗試提交,confirm階段確定提交,cancel取消提交釋放資源。

1.2.x項目指南地址:https://github.com/changmingxie/tcc-transaction/wiki/%E4%BD%BF%E7%94%A8%E6%8C%87%E5%8D%971.2.x

本文的例子為引入一個本人實際工作中的一個開發(fā)場景:創(chuàng)建資產(chǎn),將資產(chǎn)信息同時同步到Mongo與ES的流程(ES代碼不列出了,與mongo類似),整個流程保證數(shù)據(jù)一致


三、項目流程


1.下載1.2.x版本源碼,并可能需要修改部分代碼


因為是第三方包,所以需要自己打包到本地倉庫。但包中spring版本為3.2.12.RELEASE,如果本地項目為4.x,比如本人的項目spring版本為4.3.4.RELEASE,如果不修改tcc中的spring版本,將報錯無法啟動,所以需要對原有框架源碼進行相應的修改。

源碼修改比較簡單,如下


1.1 修改tcc-transaction總pom.xml文件 


<!-- 第一處:修改版本為4.3.4 --><springframework.version>4.3.4.RELEASE</springframework.version> <!-- 第二處:修改版本為2.2.1 --><dependency> <groupId>org.quartz-scheduler</groupId> <artifactId>quartz</artifactId> <version>2.2.1</version> <exclusions> <exclusion> <groupId>c3p0</groupId> <artifactId>c3p0</artifactId> </exclusion> </exclusions></dependency> <!-- 第三處:修改版本為2.5.3 --><dependency> <groupId>com.alibaba</groupId> <artifactId>dubbo</artifactId> <version>2.5.3</version></dependency>


1.2 修改 Java類

tcc-transaction-spring/src/main/java/org/mengyun/tcctransaction/spring/recover/RecoverScheduledJob.java

該文件中 CronTriggerBean類在4.x中已經(jīng)不存在,也是修改源碼主要修改的地方。

修改其中的init方法,修改后如下:


public void init() { try { MethodInvokingJobDetailFactoryBean jobDetail = new MethodInvokingJobDetailFactoryBean(); jobDetail.setTargetObject(transactionRecovery); jobDetail.setTargetMethod("startRecover"); jobDetail.setName("transactionRecoveryJob"); jobDetail.setConcurrent(false); jobDetail.afterPropertiesSet();  CronTriggerFactoryBean cronTrigger = new CronTriggerFactoryBean(); cronTrigger.setBeanName("transactionRecoveryCronTrigger"); cronTrigger.setJobDetail(jobDetail.getObject());  cronTrigger.setCronExpression(transactionConfigurator.getRecoverConfig().getCronExpression()); cronTrigger.afterPropertiesSet();  scheduler.scheduleJob(jobDetail.getObject(), cronTrigger.getObject());  scheduler.start();  } catch (Exception e) { throw new SystemException(e); }}


各位也可參考如下的修改:https://github.com/changmingxie/tcc-transaction/pull/84/files


1.3 打包并發(fā)布


這里我們通過Maven進行打包發(fā)布,命令為:


mvn -Dmaven.test.skip=true install


2.項目依賴


參考1.2.x使用指南,引入兩個依賴(本人項目dubbo/dubbox框架,我使用并打包時版本為1.2.3.1)。調用方和提供方都需要引入依賴。


3.加載tcc-transaction.xml配置


原文中是配置在web.xml中,我個人試了一下放在dubbo web項目的web.xml中,但配置并沒有被加載。該文件的意義只是希望項目啟動時被加載,于是直接在dubbo中的一個spring的配置文件中引入,如下:


<!-- TCC Transaction --><import resource="classpath:tcc-transaction.xml" />

該文件里面提供各種aop邏輯,項目啟動時掃描指定注解,并做增強。


4.設置TransactionRepository‘


需要為tcc配置數(shù)據(jù)源,可以是MySQL或其他nosql,本文使用mysql,其他可參見原指南文檔。
mysql配置如下:

<!--tcc--><bean id="tccDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${jdbc.driverClassName}" /> <property name="url" value="${jdbc.tcc.url}" /> <property name="username" value="${jdbc.username}" /> <property name="password" value="${jdbc.password}" /> <property name="initialSize" value="${dbcp.initialSize}" /> <property name="maxActive" value="${dbcp.maxActive}" /> <property name="maxIdle" value="${dbcp.maxIdle}" /> <property name="maxWait" value="${dbcp.maxWait}" /> <property name="poolPreparedStatements" value="${dbcp.poolPreparedStatements}" /> <property name="defaultAutoCommit" value="${dbcp.defaultAutoCommit}" /> <property name="timeBetweenEvictionRunsMillis" value="${dbcp.timeBetweenEvictionRunsMillis}" /> <property name="minEvictableIdleTimeMillis" value="${dbcp.minEvictableIdleTimeMillis}" /></bean> <bean id="transactionRepository" class="org.mengyun.tcctransaction.spring.repository.SpringJdbcTransactionRepository"> <property name="dataSource" ref="tccDataSource"/> <property name="domain" value="SAAS"/> <property name="tbSuffix" value="_ASSET"/></bean> <bean class="org.mengyun.tcctransaction.spring.recover.DefaultRecoverConfig"> <property name="maxRetryCount" value="30"/> <property name="recoverDuration" value="120"/> <property name="cronExpression" value="0 */1 * * * ?"/> <property name="delayCancelExceptions"> <util:set> <value>com.alibaba.dubbo.remoting.TimeoutException</value> </util:set> </property></bean>


需要注意的點:

1.數(shù)據(jù)源必須配置新的,不能使用之前項目存在的dataSource的bean,也不能在同一庫中,不然會導致tcc表數(shù)據(jù)與本地事務一起回滾,從而無法保存異常事務日志;

2.注意domain、tbSuffix的配置,這兩項文檔中并沒有配置,但源碼demo中配置了,用于數(shù)據(jù)庫的表名稱等,推薦配置;

3.最后的DefaultRecoverConfig項是可選的,用于恢復與重試,具體作用參考使用指南;

4.defaultAutoCommit必須為true(默認為true)


5.mysql建表腳本


根據(jù)以上的tbSufifix配置,腳本如下:


CREATE TABLE `tcc_transaction_asset` ( `TRANSACTION_ID` int(11) NOT NULL AUTO_INCREMENT, `DOMAIN` varchar(100) DEFAULT NULL, `GLOBAL_TX_ID` varbinary(32) NOT NULL, `BRANCH_QUALIFIER` varbinary(32) NOT NULL, `CONTENT` varbinary(8000) DEFAULT NULL, `STATUS` int(11) DEFAULT NULL, `TRANSACTION_TYPE` int(11) DEFAULT NULL, `RETRIED_COUNT` int(11) DEFAULT NULL, `CREATE_TIME` datetime DEFAULT NULL, `LAST_UPDATE_TIME` datetime DEFAULT NULL, `VERSION` int(11) DEFAULT NULL, PRIMARY KEY (`TRANSACTION_ID`), UNIQUE KEY `UX_TX_BQ` (`GLOBAL_TX_ID`,`BRANCH_QUALIFIER`)) ENGINE=InnoDB DEFAULT CHARSET=utf8


如果表名稱不對,啟動過程會報錯,這時,對數(shù)據(jù)表做相應調整即可。


6.發(fā)布服務(重點)


6.1 dubbo接口


 /** * @author binghe * 資產(chǎn)相關的業(yè)務發(fā)布Dubbo服務 */public interface AssetCardService {  /** * 測試預保存資產(chǎn)(狀態(tài)為待確認) */ @Compensable int testSaveAssetCard(AssetCardModel model);  /** * 確認保存資產(chǎn)到mysql(狀態(tài)為正常) */ int confirmMysqlSaveAssetCard(AssetCardModel model);  /** * 取消保存資產(chǎn)到msyql(更新狀態(tài)為刪除) */ int cancelMysqlSaveAssetCard(AssetCardModel model);  /** * 預保存資產(chǎn)到mongo(狀態(tài)為待確認) */ @Compensable void processMongo(AssetCardModel model);  /** * 確認保存資產(chǎn)到mongo(狀態(tài)為正常) */ void confirmMongoSaveAssetCard(AssetCardModel model);  /** * 取消保存資產(chǎn)到mongo(更新狀態(tài)為刪除) */ void cancelMongoSaveAssetCard(AssetCardModel model); }


需要注意的點:
1.對外提供服務的接口必須有@Compensable注解;
2.對應的confirm與cancel方法必須聲明為接口,不能聲明為private,即使是public也不行,必須有接口。


6.2 dubbo接口實現(xiàn)類


/*** @author binghe* 資產(chǎn)相關的業(yè)務發(fā)布Dubbo服務的實現(xiàn)*/@Service@Componentpublic class AssetCardServiceImpl implements AssetCardService{ @Override @Compensable(confirmMethod = "confirmMysqlSaveAssetCard", cancelMethod = "cancelMysqlSaveAssetCard", transactionContextEditor = DubboTransactionContextEditor.class) @Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class }) public int testSaveAssetCard(AssetCardModel model){  // 保存mysql,data狀態(tài)為-1 model.setDataStatus(-1); assetCardDao.insert(model);   // mongo處理 assetCardService.processMongo(model);  return model.getId(); }  @Override public int confirmMysqlSaveAssetCard(AssetCardModel model){ System.out.println("============================================================================"); System.out.println("=================mysql:confirm"); System.out.println("============================================================================");  // 更新mysql data_status為0 model.setDataStatus(0); assetCardDao.updateByPrimaryKey(model);  return model.getId(); }  @Override public int cancelMysqlSaveAssetCard(AssetCardModel model){ System.out.println("============================================================================"); System.out.println("=================mysql:cancel"); System.out.println("============================================================================");  // 更新mysql data_status為-1 model.setDataStatus(-1); assetCardDao.updateByPrimaryKey(model);  return model.getId(); }  @Compensable(confirmMethod = "confirmMongoSaveAssetCard", cancelMethod = "cancelMongoSaveAssetCard", transactionContextEditor = DubboTransactionContextEditor.class) @Override public void processMongo(AssetCardModel model) {  // 保存mongo,data_statu為-1 model.setDataStatus(-1); assetCardDaoWrapper.saveMongo(model); }  @Override public void confirmMongoSaveAssetCard(AssetCardModel model){ System.out.println("============================================================================"); System.out.println("=================mongo:confirm"); System.out.println("============================================================================");  // 更新mongo data_status為0 model.setDataStatus(0); assetCardDaoWrapper.updateMongo(model); }  @Override public void cancelMongoSaveAssetCard(AssetCardModel model){ System.out.println("============================================================================"); System.out.println("=================mongo:cancel"); System.out.println("============================================================================");  // 更新mongo data_status為-1 model.setDataStatus(-1); assetCardDao.updateByPrimaryKey(model); assetCardDaoWrapper.updateMongo(model); }}


注意點:

1.對外提供服務的接口必須有@Compensable注解,同時必須有confirmMethod、cancelMethod參數(shù)的配置,同時dubbo接口額外增加 "transactionContextEditor = DubboTransactionContextEditor.class"這個配置;

2.提供服務接口與對應另外的兩個CC方法參數(shù)必須完全一致;

3.該tcc框架可嵌套調用,如上在testSaveAssetCard方法,即try階段中調用了另一個tcc方法"assetCardService.processMongo()",理論上嵌套只應該在try階段進行;

4.confirm、cancel需要實現(xiàn)冪等性,可能會被重試;5.由于網(wǎng)絡等因素,可能導致cancel方法先執(zhí)行,cancel方法一定要做好相應的判斷與處理


6.3 調用方

@Override@Transactional(propagation = Propagation.REQUIRED, rollbackFor = { Exception.class })public long testSaveAssetCard(AssetCardModel assetCardModel) throws AssetException { assetCardModel.setId(IdGenerator.getId());  return assetCardService.testSaveAssetCard(assetCardModel);}


注意點:

1.因為需要回滾更新等操作,所以此業(yè)務中id不能用自增,而是需要項目生成;

2.特別注意,調用方必須在事務中,也就是說必須有事務注解,或者能被事務配置切到,沒有事務tcc框架調用時會拋異常。

至此,配置已經(jīng)全部完成。


7.事務查看


源碼中提供tcc-transaction-server web項目,該項目提供界面查看事務日志,打包后部署即可,我們這里就不在作詳細的描述。


四、TCC執(zhí)行流程


業(yè)務流程使用記錄:

前提:用戶下單,建立訂單,創(chuàng)建支付記錄,支付記錄狀態(tài)為待支付

try:

用戶金額凍結

調用積分處理TCC:

try:預增加積分

confirm:更新增加積分狀態(tài)

cancel:取消增加的積分

confirm:

訂單支付狀態(tài)更新為已支付

訂單支付記錄支付狀態(tài)更新為已支付

用戶金額扣款(以上三個操作在同一本地事務)

cancel:

判斷訂單支付狀態(tài)與訂單記錄支付狀態(tài)為未支付

用戶凍結金額釋放


特別推薦一個分享架構+算法的優(yōu)質內容,還沒關注的小伙伴,可以長按關注一下:

【分布式事務】tcc-transaction分布式TCC型事務框架搭建與實戰(zhàn)案例(基于Dubbo/Dubbox)

長按訂閱更多精彩▼

【分布式事務】tcc-transaction分布式TCC型事務框架搭建與實戰(zhàn)案例(基于Dubbo/Dubbox)

如有收獲,點個在看,誠摯感謝

免責聲明:本文內容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關機構授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內容真實性等。需要轉載請聯(lián)系該專欄作者,如若文章內容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: 驅動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設備,其驅動電源的性能直接關系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅動電源設計中至關重要的兩個環(huán)節(jié),集成化方案的設計成為提升電機驅動性能的關鍵。

關鍵字: 工業(yè)電機 驅動電源

LED 驅動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設備的使用壽命。然而,在實際應用中,LED 驅動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設計、生...

關鍵字: 驅動電源 照明系統(tǒng) 散熱

根據(jù)LED驅動電源的公式,電感內電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關鍵字: LED 設計 驅動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術之一是電機驅動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅動系統(tǒng)中的關鍵元件,其性能直接影響到電動汽車的動力性能和...

關鍵字: 電動汽車 新能源 驅動電源

在現(xiàn)代城市建設中,街道及停車場照明作為基礎設施的重要組成部分,其質量和效率直接關系到城市的公共安全、居民生活質量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關鍵字: 發(fā)光二極管 驅動電源 LED

LED通用照明設計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關鍵字: LED 驅動電源 功率因數(shù)校正

在LED照明技術日益普及的今天,LED驅動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關鍵字: LED照明技術 電磁干擾 驅動電源

開關電源具有效率高的特性,而且開關電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅動電源

關鍵字: LED 驅動電源 開關電源

LED驅動電源是把電源供應轉換為特定的電壓電流以驅動LED發(fā)光的電壓轉換器,通常情況下:LED驅動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: LED 隧道燈 驅動電源
關閉