詳解Spring Boot微服務如何集成fescar解決分布式事務問題
什么是fescar?
關于fescar的詳細介紹,請參閱fescar wiki。
傳統(tǒng)的2PC提交協(xié)議,會持有一個全局性的鎖,所有局部事務預提交成功后一起提交,或有一個局部事務預提交失敗后一起回滾,最后釋放全局鎖。鎖持有的時間較長,會對并發(fā)造成較大的影響,死鎖的風險也較高。
fescar的創(chuàng)新之處在于,每個局部事務執(zhí)行完立即提交,釋放本地鎖;它會去解析你代碼中的sql,從數(shù)據(jù)庫中獲得事務提交前的事務資源即數(shù)據(jù),存放到undo_log中,全局事務協(xié)調(diào)器在回滾的時候直接使用undo_log中的數(shù)據(jù)覆蓋你提交的數(shù)據(jù)。
Spring Boot如何集成fescar?
我們可以從官方代碼庫中看到,fescar目前提供的示例是針對使用dubbo的服務,那Spring Boot的項目如何集成fescar呢?
和很多2PC提交協(xié)議(如tx_lcn)的解決方案一樣,fescar也是在數(shù)據(jù)源處做了代理,和事務協(xié)調(diào)器進行通信,來決定本地事務是否回滾。所以,第一步,在你的spring boot項目中,首先應使用fescar提供的代理數(shù)據(jù)源作為你的數(shù)據(jù)源,例如:
DruidDataSource dataSource = initDataSource(dataSourceProps.get("url").toString(), dataSourceProps.get("username").toString(), dataSourceProps.get("password").toString()); DataSourceProxy proxy = new DataSourceProxy(dataSource);
然后,你需要創(chuàng)建一個Feign攔截器,把RootContext中的XID(XID用于標識一個局部事務屬于哪個全局事務,需要在調(diào)用鏈路的上下文中傳遞)傳遞到上層調(diào)用鏈路。
@Component public class RequestHeaderInterceptor implements RequestInterceptor { @Override public void apply(RequestTemplate template) { String xid = RootContext.getXID(); if(StringUtils.isNotBlank(xid)){ template.header("Fescar-Xid",xid); } } }
最后,你需要創(chuàng)建一個Http Rest請求攔截器,用于把當前上下文中獲取到的XID放到RootContext。
import com.alibaba.fescar.core.context.RootContext; import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.web.filter.OncePerRequestFilter; import javax.servlet.FilterChain; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; public class FescarXidFilter extends OncePerRequestFilter { protected Logger logger = LoggerFactory.getLogger(FescarXidFilter.class); @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { String xid = RootContext.getXID(); String restXid = request.getHeader("Fescar-Xid"); boolean bind = false; if(StringUtils.isBlank(xid)&&StringUtils.isNotBlank(restXid)){ RootContext.bind(restXid); bind = true; if (logger.isDebugEnabled()) { logger.debug("bind[" + restXid + "] to RootContext"); } } try{ filterChain.doFilter(request, response); } finally { if (bind) { String unbindXid = RootContext.unbind(); if (logger.isDebugEnabled()) { logger.debug("unbind[" + unbindXid + "] from RootContext"); } if (!restXid.equalsIgnoreCase(unbindXid)) { logger.warn("xid in change during http rest from " + restXid + " to " + unbindXid); if (unbindXid != null) { RootContext.bind(unbindXid); logger.warn("bind [" + unbindXid + "] back to RootContext"); } } } } } }
這樣就完成了fescar的集成。
開始使用吧!
首先在項目中初始化兩個Bean:
@Bean public FescarXidFilter fescarXidFilter(){ return new FescarXidFilter(); } @Bean public GlobalTransactionScanner scanner(){ GlobalTransactionScanner scanner = new GlobalTransactionScanner("fescar-test","my_test_tx_group"); return scanner; }
然后寫兩個服務,服務A調(diào)用服務B,并在A服務的調(diào)用方法上打上@GlobalTransactional標簽:
@GlobalTransactional(timeoutMills = 300000, name = "fescar-test-tx") public void testFescar() throws BusinessException { DictionVO dictionVO = new DictionVO(); dictionVO.setCode("simidatest"); dictionVO.setValue("1"); dictionVO.setDesc("simidatest"); dictionVO.setAppId("sso"); commonService.createDiction(dictionVO);//遠程調(diào)用服務B areaMapper.deleteAreaBySysNo(2);//本地事務 throw new BusinessException("主動報錯"); }
最后,兩個項目中添加application.conf文件,用于告訴客戶端如何與分布式協(xié)調(diào)器通信,官方示例中有這個文件,就不在此貼代碼啦,application.conf傳送門
啟動事務協(xié)調(diào)器,sh fescar-server.sh 8091 ~/dksl/git/fescar/data,啟動你的項目,開始測試吧!
last thing
分布式事務作為微服務應用中的老大難問題,在現(xiàn)有的解決方案中,個人認為fescar是目前最輕量并且代價最小的一種解決方案。目前的版本,事務協(xié)調(diào)器還不能分布式部署,官方給出的路線圖是在三月底會有第一個生產(chǎn)可用版本。讓我們一起參與到fescar的社區(qū)中,共同推動fescar生態(tài)建設,讓落地微服務不必再擔心分布式事務的問題。
以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
- SpringMVC中事務是否可以加在Controller層的問題
- Spring事務失效的一種原因關于this調(diào)用的問題
- JAVA Spring中讓人頭痛的JAVA大事務問題要如何解決你知道嗎
- 解決Spring或SpringBoot開啟事務以后無法返回自增主鍵的問題
- 解決try-catch捕獲異常信息后Spring事務失效的問題
- Spring事務失效問題分析及解決方案
- SpringBoot內(nèi)部調(diào)用事務不起作用問題的解決方案
- Spring聲明式事務和@Aspect的攔截順序問題的解決
- 解決spring mvc 多數(shù)據(jù)源切換,不支持事務控制的問題
- Spring中事務幾個常見的問題解決
相關文章
SpringSecurity 自定義表單登錄的實現(xiàn)
這篇文章主要介紹了SpringSecurity 自定義表單登錄的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-01-01jvm雙親委派 vs 破壞雙親委派理解加載器的權(quán)責分配
這篇文章主要為大家介紹了jvm雙親委派 vs 破壞雙親委派對比來理解加載器的權(quán)責分配,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-10-10如何解決Maven打包時每次都出現(xiàn)Download maven-metadata.xml卡住問題
這篇文章主要介紹了如何解決Maven打包時每次都出現(xiàn)Download maven-metadata.xml卡住問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-05-05