日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
知道這些坑,你還敢亂把單體架構(gòu)拆成分布式嗎?

一、背景

我們在聊架構(gòu)風(fēng)格之前先明確一個問題,什么是架構(gòu)?我們?yōu)槭裁匆x擇架構(gòu)、用來解決哪些問題?

十載專注成都網(wǎng)站制作,企業(yè)網(wǎng)站設(shè)計,個人網(wǎng)站制作服務(wù),為大家分享網(wǎng)站制作知識、方案,網(wǎng)站設(shè)計流程、步驟,成功服務(wù)上千家企業(yè)。為您提供網(wǎng)站建設(shè),網(wǎng)站制作,網(wǎng)頁設(shè)計及定制高端網(wǎng)站建設(shè)服務(wù),專注于企業(yè)網(wǎng)站設(shè)計,高端網(wǎng)頁制作,對水泥攪拌車等多個行業(yè),擁有豐富設(shè)計經(jīng)驗。

1、什么是架構(gòu)

書本定義:“軟件的架構(gòu)是一種抽象的結(jié)構(gòu),他由軟件的各個組成部分和這些部分之間的依賴關(guān)系構(gòu)成”。我的理解是,架構(gòu)就是根據(jù)業(yè)務(wù)選擇合適的技術(shù)、中間件,并且按照合適的設(shè)計模式對這些模塊,進行組裝來滿足業(yè)務(wù)特性的需求。

2、選擇架構(gòu)風(fēng)格的目的

我們選擇架構(gòu)風(fēng)格的初衷在于 “三更原則”(自己的理解) :更好地降本提效、更快地發(fā)版上線、更好地維護系統(tǒng)穩(wěn)定性。

任何一個架構(gòu)風(fēng)格,都可以實現(xiàn)功能性需求,但是一個好的架構(gòu)風(fēng)格能在功能性需求之上,提升非功能性需求,那么你可能會問,什么是非功能性需求?舉例:擴展性、穩(wěn)定性等等。

這里我將會以我認知結(jié)合踩過的坑,來給大家詳細講一下,我們是如何從單體架構(gòu)演進到分布式架構(gòu),在向分布式單體架構(gòu)的演進的道路上,又如何進行的抉擇,以及為什么最后同時選擇了微服務(wù)架構(gòu)+分布式架構(gòu)的原因。接下來就結(jié)合一個系統(tǒng)來作為案例,貫穿主線講解。

首先來講一下,最初的單體架構(gòu)的經(jīng)歷和轉(zhuǎn)型。

二、單體架構(gòu)

我們在系統(tǒng)創(chuàng)建之初,往往都是集中業(yè)務(wù)、單點部署系統(tǒng),所有業(yè)務(wù)打一個包,快速上線。滿足了業(yè)務(wù)初期的快速發(fā)版上線,而且適合中小公司沒有自己的paas平臺,應(yīng)對初期快速迭代的業(yè)務(wù),開發(fā)、迭代、測試、發(fā)布都是非常的便捷。那么單體架構(gòu)都有什么類型呢?

1、單體架構(gòu)的類型

單體架構(gòu)也分為大泥團架構(gòu)、分層單體架構(gòu)、模塊化單體架構(gòu),他們的區(qū)別是什么呢?

1)大泥團單體架構(gòu):毫無分層、所有模塊聚焦在一起,相互穿插(除非是你接手需要改造,否則不要創(chuàng)建這樣的架構(gòu)風(fēng)格,這種大泥團架構(gòu)很難拆分,到最后的下場往往都是重新搭建)。

2)分層單體架構(gòu):普遍的選擇,架構(gòu)進行了簡單的分層,比如傳統(tǒng)的mvc三層架構(gòu)。

3)模塊化單體架構(gòu):一般是隨著業(yè)務(wù)的發(fā)展,由分層單體架構(gòu)演變而來,特點就是引入了多個業(yè)務(wù)模塊并且提供相應(yīng)的服務(wù)能力。

2、單體架構(gòu)的優(yōu)缺點

1)單體架構(gòu)的優(yōu)點

  • 應(yīng)用的開發(fā)很簡單
  • 易于對應(yīng)用程序大規(guī)模的更改
  • 測試相對簡單、直觀
  • 部署簡單明了
  • 橫向擴展不費吹灰之力

在業(yè)務(wù)的初期,單體架構(gòu)的優(yōu)點,無論從哪個方面來說,都優(yōu)于其他架構(gòu)風(fēng)格,但是隨著業(yè)務(wù)的增加、耦合,單體架構(gòu)的缺點也逐漸暴露出來,這個也符合“康威定律”。那么單體架構(gòu)的“后期”會暴露出哪些問題呢?

2)單體架構(gòu)的缺點

  • 代碼庫膨脹
  • 過度的復(fù)雜性會嚇退開發(fā)者
  • 開發(fā)速度慢
  • 從代碼提交到實際部署的周期很長,而且容易出問題
  • 難以擴展
  • 系統(tǒng)的穩(wěn)定性得不到保障
  • 需要長期依賴某個可能過時的技術(shù)棧

單體架構(gòu)的這些缺點,其實影響的還是我上面提到的“三更原則”。經(jīng)過上面的鋪墊,相信大家已經(jīng)對單體架構(gòu)風(fēng)格已經(jīng)有了簡單的理解,那么光有方法論是不行的,我們得結(jié)合項目以及代碼片段來加深理解,做到真正的應(yīng)用。

接下來我就用一個庫存系統(tǒng)來進行串聯(lián)進行講解。先通過這張圖來了解下庫存系統(tǒng)是用來做什么的?

  • 創(chuàng)建之初,1個服務(wù)提供商品庫存維護、庫存查詢、庫存扣減能力。
  • 隨著業(yè)務(wù)的發(fā)展,庫存面向多個服務(wù):B端業(yè)務(wù),平臺內(nèi)部業(yè)務(wù)系統(tǒng)、平臺外部中臺。C端業(yè)務(wù),訂單商品扣減庫存、網(wǎng)關(guān)查詢庫存數(shù)量。

3、單體架構(gòu)的案例:庫存系統(tǒng)

最初的庫存代碼分層如下:

  • API:對外提供的dubbo服務(wù)
  • common:封裝了公共方法
  • dao:封裝了數(shù)據(jù)庫dbcp交互
  • domain:實體類
  • innerApi:系統(tǒng)內(nèi)部api交互
  • router:廢棄
  • rpc:上下游rpc交互
  • service:業(yè)務(wù)邏輯層
  • web:web服務(wù)層
  • worker:任務(wù)調(diào)度層

在最初很長的一段時間里,我們部署了兩個單體服務(wù),一個是API接口來保障上游的庫存查詢以及調(diào)用,另一個是web服務(wù)的后臺管理平臺。這兩個單體服務(wù)很好的貼合了最初的業(yè)務(wù)迭代和發(fā)版速度,但是后來隨著業(yè)務(wù)的增加附加調(diào)用量的增加,單體服務(wù)的無論是從性能和穩(wěn)定性都出現(xiàn)了較大的波動。

4、意料之外,情理之中的事故慘案

2015年6月26日晚,也是一個促銷活動的前夕,庫存的web管理平臺掛了,原因就是大量庫存導(dǎo)入,服務(wù)器的內(nèi)存不足導(dǎo)致機器宕機。商家、運營無法通過導(dǎo)表的方式去維護庫存數(shù)量,在這之前已經(jīng)經(jīng)歷過了多次橫向擴容。還是出現(xiàn)了預(yù)料之外的流量和穩(wěn)定性的問題。

而且在接下來的大促過程當中,庫存的單體服務(wù)API接口也承受了非常大的壓力。

一方面是上游調(diào)用方有很多,比如APP端首頁中的門店網(wǎng)關(guān),查詢商品是否有庫存,是否展示。購物車加車,也會查詢商品庫存的數(shù)量,提單則會對庫存數(shù)量進行扣減,乃至后續(xù)的訂單取消同樣也會調(diào)用庫存接口。

另一方面大的KA商家通過中臺對接對庫存進行操作,為了盡可能的讓商家門店的庫存和線上平臺的庫存保持一致,減少線上線下庫存不一致導(dǎo)致的超賣、少賣。中臺同步間隔時間都非常短,5分鐘-10分鐘就要全量同步一次。后續(xù)隨著入駐的商家增多,這個量級增長得也非常的迅速。于是我們開啟了單體服務(wù)向分布式服務(wù)演進的大門。

三、分布式架構(gòu)

1、分布式架構(gòu)的優(yōu)缺點

1)分布式架構(gòu)的優(yōu)點

  • 可擴展性高
  • 系統(tǒng)容錯性高
  • 業(yè)務(wù)代碼可讀性高
  • 維護簡單

這些優(yōu)點正是我們當時庫存系統(tǒng)欠缺的,尤其是其中的可用性、系統(tǒng)容錯性,是我們系統(tǒng)演進迭代的首要目標。

《分布式架構(gòu)體系》中描述到,分布式架構(gòu)的核心理念也是按照(功能、業(yè)務(wù)、領(lǐng)域等)對系統(tǒng)進行拆分,通過合理的拆分結(jié)構(gòu),實現(xiàn)各業(yè)務(wù)模塊的解耦,同時通過系統(tǒng)級容錯設(shè)計,在廉價硬件基礎(chǔ)設(shè)施上構(gòu)建起高可用、可擴展的開放技術(shù)體系。

所以我們庫存系統(tǒng)到底要按照什么進行拆分,功能?業(yè)務(wù)?領(lǐng)域?在拆分之前我們一定要明確設(shè)計的目標,避免目標方向錯誤帶來的人力、成本資源的浪費。在弄清楚目標之前,我們先了解下分布式架構(gòu)的缺點,通過了解這些缺點來衡量滿足我們目標的前提下,需要進行哪些方面的取舍,就如CAP原則一樣,只能滿足其中的兩個,AP或者CP。

2)分布式架構(gòu)的缺點

  • 服務(wù)多,人員對拆分后的業(yè)務(wù)模塊理解要花費一些成本
  • 技術(shù)棧升級耗費人力
  • 分布式事務(wù)的保持
  • 業(yè)務(wù)模塊之間的rpc交互損耗

庫存系統(tǒng)的特點,高可用、高并發(fā)、強數(shù)據(jù)一致性。接下來我們就來講一下,庫存是如何從單體架構(gòu)向分布式架構(gòu)進行的轉(zhuǎn)型。

2、單體架構(gòu)如何向分布式架構(gòu)轉(zhuǎn)型

因為庫存面臨的最大的問題是穩(wěn)定性,所以我們首先針對功能進行了拆分。

1)功能拆分

這一步是相對簡單的,我們梳理出庫存面向服務(wù)的業(yè)務(wù)方進行服務(wù)劃分。這部分無需進行太多代碼的改造,一套接口通過變更不同的group別名,部署到不同的集群即可。

拆分后,不同的服務(wù)應(yīng)對不同的業(yè)務(wù)方,系統(tǒng)錯誤的隔離性好,不會說出現(xiàn)一損俱損的局面,穩(wěn)定性上也有了保障。在解決了穩(wěn)定性的問題后,留給我們了一些喘氣的間隔,可以有時間去進行代碼的優(yōu)化。因為剛才也提到了,我們只是通過分布式的集群部署來解決容錯性的問題,但是代碼還是一套,臃腫的代碼也會拖慢我們的開發(fā)上線速度。那么接下來要進行的就是,對業(yè)務(wù)代碼的解耦,這塊也是難度最高的。我們是如何做的呢?

2)業(yè)務(wù)拆分

業(yè)務(wù)拆分的思路是什么呢?

  • 以業(yè)務(wù)本身為導(dǎo)向,充分了解系統(tǒng)業(yè)務(wù)模型,劃分業(yè)務(wù)邊界
  • 業(yè)務(wù)依賴的范圍,細分功能,盡量減少功能之間的重復(fù)依賴
  • 根據(jù)拆分功能的影響大小進行評估,拆小保大
  • 拆分的過程中不要修改業(yè)務(wù)邏輯,不要進行拆分之外的任何優(yōu)化動作(除非是bug)
  • 基于上述拆分的思路,庫存系統(tǒng)又是如何劃分的業(yè)務(wù)模塊呢?動了哪些代碼?

3)如何劃分業(yè)務(wù)模塊

關(guān)于業(yè)務(wù)劃分,網(wǎng)上有很多方法論,事件風(fēng)暴法、四色建模法等等,但是萬法不離其宗,那就是圍繞事件。以庫存系統(tǒng)舉例:庫存初始化(門店+sku庫存創(chuàng)建)、庫存數(shù)量維護(修改現(xiàn)貨數(shù)量、修改可售狀態(tài))、扣減業(yè)務(wù)(購物車扣減、提單扣減、訂單取消扣減)、提醒業(yè)務(wù)(缺貨提醒)等。每一個事件都有獨立的鏈路軸,以及時間線可以形成閉環(huán)。

4)如何在原有模塊上拆分

大多數(shù)單體架構(gòu)都是面向過程的設(shè)計,domain層充斥這個各種DTO、VO、BO,所以在層與層的數(shù)據(jù)交互過程中,大都是經(jīng)歷了多次的POJO。另外就是service層充斥著和DAO層數(shù)據(jù)交互以及參雜了業(yè)務(wù),而且嚴重違反了依賴倒置原則,整個層變得非常的沉重。這里舉個例子:

  • 同層級間相互引用
  • service層包含了太多業(yè)務(wù)邏輯,無法保障原子性

這里截取部分代碼片段作為案例,來講述下我們在拆分業(yè)務(wù)的過程中,需要做一些什么操作。

  • 對service層進行CQS的拆分
  • 把業(yè)務(wù)邏輯從原有的service層抽離,保障service方法遵循SRP原則。
  • 新增業(yè)務(wù)聚合層(或者向六邊形架構(gòu)里提到的adapter轉(zhuǎn)接口)來聚合service層的方法

①原始代碼

@Service
public class SkuMainServiceImpl implements SkuMainService {
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(SkuMainServiceImpl.class);
@Resource
private SkuMainDao skuMainDao;
@Resource
private ZkConfManagerCenterService zkConfManagerCenterService;
@Resource
private ProductImagesService productImagesService;//同級互相引用,未遵循依賴倒置
@Resource
private MqService mqServiceImpl;
@Value("${system.group.environment}")
private String systemGroupEnvironment;
/**
* 問題:service層聚合了太多業(yè)務(wù)邏輯 倒置上層方法沒辦法統(tǒng)一
* @param skuMainInfoMQEntity
* @throws Exception
*/
public void editorSaveProuct(SkuMainInfoMQEntity skuMainInfoMQEntity) throws Exception {
try {
SkuMainBean skuMainBean = skuMainInfoMQEntity.getSkuMainBean();
if (skuMainBean == null) {
throw new Exception("修改參數(shù)為空!");
}
SkuMainBean originalSku = this.getSkuMainBeanBySkuId(skuMainBean.getId());
if (originalSku == null) {
throw new Exception("無效SkuId!");
}
SkuMainBean skuMainUpdate = updateIsWeightMark(skuMainBean);
SkuMainBean skuMainPre = this.get(skuMainUpdate.getId());
// 系統(tǒng)下架的商品 強制下架
if (skuMainPre != null && skuMainPre.getSystemFixedStatus() != null && skuMainPre.getSystemFixedStatus().equals(SystemFixedStatusEnum.SYSTEM_FIXED_STATUS_DOWN.getCode())) {
skuMainUpdate.setFixedStatus(FixedStatusEnum.PRODUCT_DOWN.getCode());
}
boolean flag = skuMainDao.editorProduct(skuMainUpdate);
if (flag) {
if (!zkConfManagerCenterService.isDefaultStoreStatisticsScore(skuMainBean.getOrgCode())) {
SkuMainBean saveSkumainBean = this.get(skuMainUpdate.getId());
// 防止未查到,把緩存覆蓋
if (saveSkumainBean != null) {
cacheSkuMainBean(saveSkumainBean);
}
// 發(fā)送Sku修改MQ
sendSkuModifyMq(SkuModifyOpSourceEnum.MIX_UPDATE_SKU, originalSku, new SkuMainInfoMQEntity(skuMainUpdate));
ProductImagesBean productImagesBean = productImagesService.queryImagesBySkuId(skuMainUpdate.getId());
SkuMainInfoCheckMQEntity skuMainInfoCheckMQEntity = new SkuMainInfoCheckMQEntity();
skuMainInfoCheckMQEntity.setSkuMainBean(skuMainUpdate);
skuMainInfoCheckMQEntity.setProductImagesBean(productImagesBean);
mqServiceImpl.sendJosMQ(skuMainInfoCheckMQEntity, MqTypeEnum.RcsKeyWordsCheck);
mqServiceImpl.sendJosMQ(skuMainInfoCheckMQEntity, MqTypeEnum.SenseKeyWordsCheck);
} else {
LOGGER.info("add open platform sku , not not not send mq! skuId = {}", skuMainBean.getId());
}
}
} catch (Exception e) {
LOGGER.error("修改商品信息失敗.e:", e);
throw new Exception(e);
}
}

②CQS和SRP的改造,拆解GOD Classes

  • Read服務(wù)

  • Write服務(wù)

③抽離到業(yè)務(wù)層business層后

@Service
public class SkuMainBusinessServiceImpl implements SkuMainBusinessService {
private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(SkuMainBusinessServiceImpl.class);
@Resource
private ZkConfManagerCenterService zkConfManagerCenterService;
@Resource
private MqService mqService;
@Resource
private SkuMainReadservice skuMainReadservice;
@Resource
private SkuMainWriteservice skuMainWriteservice;
@Value("${system.group.environment}")
private String systemGroupEnvironment;
/**
* 問題:service層聚合了太多業(yè)務(wù)邏輯 倒置上層方法沒辦法統(tǒng)一
* @param skuMainInfoMQEntity
* @throws Exception
*/
public void editorSaveProuct(SkuMainInfoMQEntity skuMainInfoMQEntity) throws Exception {
try {
SkuMainBean skuMainBean = skuMainInfoMQEntity.getSkuMainBean();
if (skuMainBean == null) {
throw new Exception("修改參數(shù)為空!");
}
SkuMainBean originalSku = skuMainReadservice.getSkuMainBeanBySkuId(skuMainBean.getId());
if (originalSku == null) {
throw new Exception("無效SkuId!");
}
SkuMainBean skuMainUpdate = skuMainWriteservice.updateIsWeightMark(skuMainBean);
SkuMainBean skuMainPre = skuMainReadservice.queryDbById(skuMainUpdate.getId());
// 系統(tǒng)下架的商品 強制下架
if (skuMainPre != null && skuMainPre.getSystemFixedStatus() != null && skuMainPre.getSystemFixedStatus().equals(SystemFixedStatusEnum.SYSTEM_FIXED_STATUS_DOWN.getCode())) {
skuMainUpdate.setFixedStatus(FixedStatusEnum.PRODUCT_DOWN.getCode());
}
boolean flag = skuMainWriteservice.editorProduct(skuMainUpdate);
if (flag) {
if (!zkConfManagerCenterService.isDefaultStoreStatisticsScore(skuMainBean.getOrgCode())) {
SkuMainBean saveSkumainBean = skuMainservice.queryDbById(skuMainUpdate.getId());
// 防止未查到,把緩存覆蓋
if (saveSkumainBean != null) {
skuMainWriteservice.cacheSkuMainBean(saveSkumainBean);
}
// 發(fā)送Sku修改MQ
skuMainWriteservice.sendSkuModifyMq(SkuModifyOpSourceEnum.MIX_UPDATE_SKU, originalSku, new SkuMainInfoMQEntity(skuMainUpdate));
} else {
LOGGER.info("add open platform sku , not not not send mq! skuId = {}", skuMainBean.getId());
}
}
} catch (Exception e) {
LOGGER.error("修改商品信息失敗.e:", e);
throw new Exception(e);
}
}

④構(gòu)建好的業(yè)務(wù)層

5)拆分小結(jié)

拆分到這里,業(yè)務(wù)層的劃分基本就比較清晰了,而且在這個增量整合底層代碼的過程中,面向過程的業(yè)務(wù)線也都梳理的比較清晰了,底層方法也都提取到了業(yè)務(wù)層收口,通過接口對外提供服務(wù)。那么接下來我們要面臨的問題就是,如何對具體的讀寫進行拆分。

3、基于CQRS打造分布式服務(wù)

上面我們也提到了,進行了整體功能的拆分,并沒有對具體的讀寫服務(wù)的拆分。在面向服務(wù)的場景下,功能里也是分讀服務(wù)、寫服務(wù)。那么我們有什么原則來指導(dǎo)讀寫服務(wù)的分離么?那就是CQRS的思想:命令職責(zé)查詢分離,不單單指代碼,同樣也是適用于服務(wù)。

1)優(yōu)先拆分讀還是優(yōu)先拆分寫

建議從拆分讀開始,因為讀服務(wù)相對于寫服務(wù)簡單一些,而且更容易提高系統(tǒng)對外服務(wù)的穩(wěn)定性,寫服務(wù)的流程相對底層改動比較大,測試的周期也會比較長。在前期,動寫服務(wù)系統(tǒng)出問題的概率會比較大,所以綜合穩(wěn)定性、擴展性來說,優(yōu)先拆分讀服務(wù)是一個比較好的選擇。

2)CQRS的思想適合所有業(yè)務(wù)場景嗎

以庫存系統(tǒng)舉例,我們就按照CQRS的思想復(fù)刻一版,看看會出現(xiàn)什么問題。

  • 每一次修改同步庫存寫入任務(wù)表
  • schedule任務(wù)讀取任務(wù)表
  • 把任務(wù)表的修改數(shù)據(jù)同步到Read服務(wù)中的redis中

在這個過程中,存在兩個問題:

  • 大數(shù)據(jù)量任務(wù)同步的問題。也就是Event Bus同步redis的數(shù)據(jù)同步速度問題。
  • 延遲問題。庫存要求實時性非常高,如果因為任務(wù)積壓導(dǎo)致的延遲,會讓庫存陷入困境之中。大量的庫存數(shù)量不對導(dǎo)致的超賣、超賣會瞬間擊潰業(yè)務(wù)。

所以每一個架構(gòu)、每一種思想都是要結(jié)合業(yè)務(wù)去分析,我們可以借鑒CQRS的命令查詢職責(zé)分離,在面對業(yè)務(wù)系統(tǒng)部署的時候,不要死板的遵循固有的模式,要對現(xiàn)有的風(fēng)格做出一定的取舍。所以,我們在應(yīng)對庫存業(yè)務(wù)的時候,基于CQRS的風(fēng)格創(chuàng)建出了庫存獨有的CQRS-StockCenter(名字自己起的 哈哈)

3)CQRS的活學(xué)活用:CQRS-StockCenter

  • business業(yè)務(wù)層寫入命令
  • writeService服務(wù)寫入讀服務(wù)Redis
  • MQ消息作為異步數(shù)據(jù)補全寫入mysql備份、寫入流水

庫存通過這套設(shè)計強依賴了Redis來作為庫存查詢、修改的中間件。保障了數(shù)據(jù)的強一致性。庫存在原有的服務(wù)上,分離了讀寫,保障了系統(tǒng)的CQRS命令職責(zé)查詢分離。

4)分布式的事務(wù)

我們大家都知道事務(wù),簡單來說:事務(wù)由一組關(guān)聯(lián)操作構(gòu)成,A->B->C ,如果執(zhí)行到C報錯了,那么要回滾B->A。

對于本地事務(wù)來說,這個相對很簡單,如果你用了事務(wù)型數(shù)據(jù)庫比如mysql,并且不涉及多個數(shù)據(jù)源的情況下,保障事務(wù)的ACID非常的容易。

但是我們這里要提到的就是分布式的事務(wù)。因為系統(tǒng)拆分后,每個服務(wù)是一個獨立的模塊,負責(zé)一塊業(yè)務(wù),那么在整個業(yè)務(wù)軸的流程下,各個服務(wù)節(jié)點的跨系統(tǒng)事務(wù)回滾成為了一個難題。業(yè)界也有一些方案,比如

  • JTA(Java Transaction API即Java事務(wù)API)和JTS(Java Transaction Service即Java事務(wù)服務(wù)),為J2EE平臺提供了分布式事務(wù)服務(wù)。

但是這種需要滿足XA(兩階段提交)的標準,非常的重,而且現(xiàn)在的業(yè)務(wù)多樣性,很多數(shù)據(jù)庫比如:mongo ,并不支持XA的標準分布式事務(wù),一些流行的中間件,比如RabbitMQ和kafuka也不支持分布式事務(wù)。


文章題目:知道這些坑,你還敢亂把單體架構(gòu)拆成分布式嗎?
標題來源:http://m.5511xx.com/article/djiedjc.html