互聯(lián)網(wǎng)單元化架構(gòu)設(shè)計(jì)衍變之路
隨著大型互聯(lián)網(wǎng)公司業(yè)務(wù)的多元化發(fā)展,就拿滴滴癞志、美團(tuán)等大廠(chǎng)來(lái)講往枷,如滴滴打車(chē)、單車(chē)凄杯、外賣(mài)错洁、酒店、旅行戒突、金融等業(yè)務(wù)持續(xù)高速增長(zhǎng)屯碴,單個(gè)大型分布式體系的集群,通過(guò)加機(jī)器+集群內(nèi)部拆分(kv膊存、mq导而、Mysql等),雖然具備了一定的可擴(kuò)展性膝舅。但是嗡载,隨著業(yè)務(wù)量的進(jìn)一步增長(zhǎng),這個(gè)集群規(guī)模琢漸變的巨大,從而一定會(huì)在某個(gè)點(diǎn)達(dá)到性能瓶頸,無(wú)法滿(mǎn)足擴(kuò)展性需要歪脏,并且大集群內(nèi)核服務(wù)出現(xiàn)問(wèn)題,會(huì)影響全網(wǎng)所有用戶(hù)遥巴。
以滴滴打車(chē)、美團(tuán)外賣(mài)舉例來(lái)說(shuō):
- 打車(chē)業(yè)務(wù)體量巨大享幽,尤其在早晚高峰期铲掐。全年訂單量已越10億。
- 外賣(mài)業(yè)務(wù)體量龐大值桩,目前單量突破1700w/天摆霉,對(duì)應(yīng)如此龐大的單個(gè)大型分布式集群,會(huì)面臨一下問(wèn)題:
1、容災(zāi)問(wèn)題
2携栋、資源擴(kuò)展性問(wèn)題
3搭盾、大集群拆分問(wèn)題
容災(zāi)問(wèn)題
- 核心服務(wù)(比如訂單服務(wù))掛掉,會(huì)影影響全網(wǎng)所有的用戶(hù)婉支,導(dǎo)致整個(gè)業(yè)務(wù)不可用鸯隅;
- 數(shù)據(jù)庫(kù)主庫(kù)集中在一個(gè)IDC,主機(jī)房掛掉向挖,會(huì)影響全網(wǎng)所有用戶(hù)蝌以,整個(gè)業(yè)務(wù)無(wú)法快速切換和恢復(fù)
資源擴(kuò)展問(wèn)題
- 單IDC的資源(機(jī)器、網(wǎng)絡(luò)帶寬等)已經(jīng)沒(méi)法滿(mǎn)足何之,擴(kuò)展IDC時(shí)跟畅,存在跨機(jī)房訪(fǎng)問(wèn)延時(shí)問(wèn)題(增加異地機(jī)房,時(shí)延問(wèn)題嚴(yán)重)
- 數(shù)據(jù)庫(kù)主庫(kù)單點(diǎn)帝美,連接數(shù)有限碍彭,不能支持應(yīng)用程序的持續(xù)發(fā)展晤硕;
大集群拆分問(wèn)題
- 核心問(wèn)題:分布式集群規(guī)模擴(kuò)大后悼潭,會(huì)響應(yīng)的帶來(lái)資源擴(kuò)展、大集群拆分以及容災(zāi)問(wèn)題
- 所有處于對(duì)業(yè)務(wù)擴(kuò)展性以及容災(zāi)需求的考慮舞箍,我們需要一套從底層架構(gòu)徹底解決問(wèn)題的方案舰褪,業(yè)界主流解決方案:?jiǎn)卧軜?gòu)方案
SET單元化架構(gòu)方案
同城 "雙活" 架構(gòu)介紹
目前很多大型互聯(lián)網(wǎng)公司的業(yè)務(wù)架構(gòu)可以理解為同城"雙活"架構(gòu),注意這里的“雙活"是加引號(hào)的占拍,具體可以這樣理解:
- 1、業(yè)務(wù)層面上已經(jīng)做到的真正的雙活(或者多活)捎迫,分別承擔(dān)部分流量蛔翅;
- 2鸟款、存儲(chǔ)層面比如定時(shí)任務(wù)处渣、緩存、持久層有决、數(shù)據(jù)分析等都是主從架構(gòu),會(huì)有跨機(jī)房寫(xiě)的問(wèn)題;
- 3、一個(gè)數(shù)據(jù)中心故障局冰,可以手動(dòng)切換流量,部分組件可以自動(dòng)切換产雹;
兩地三中心架構(gòu)介紹
使用災(zāi)備的思想诫惭,在同城“雙活”的基礎(chǔ)上,在異地部署一套災(zāi)備數(shù)據(jù)中心洽故,每個(gè)中心都具有完備的數(shù)據(jù)處理能力贝攒,只有當(dāng)主節(jié)點(diǎn)故障需要容災(zāi)時(shí)才會(huì)緊急啟動(dòng)備用數(shù)據(jù)中心;
SET化方案目標(biāo):
業(yè)務(wù):解決業(yè)務(wù)遇到的擴(kuò)展性和容災(zāi)等需求时甚,支撐業(yè)務(wù)的高速方案
通用性:架構(gòu)側(cè)形成統(tǒng)一通用的解決方案,方面各業(yè)務(wù)線(xiàn)接入使用
SET化架構(gòu)設(shè)計(jì):
SET化架構(gòu)策略
流量路由:
- 按照特殊的key(通常為userid)進(jìn)行路由哈踱,判斷某次請(qǐng)求該路由到中心集群還是單元化集群荒适;
中心集群:
- 為進(jìn)行單元化改造的服務(wù)(通常不在核心交易鏈路,比如供應(yīng)鏈系統(tǒng))稱(chēng)為中心集群开镣,跟當(dāng)前架構(gòu)保持一致刀诬。
單元化集群:
- 每個(gè)單元化集群只負(fù)責(zé)本單元內(nèi)的流量處理,以實(shí)現(xiàn)流量拆分以及故障隔離邪财;
- 每個(gè)單元化集群前期只存儲(chǔ)本單元產(chǎn)生的交易數(shù)據(jù)陕壹,后續(xù)會(huì)做雙向數(shù)據(jù)同步,實(shí)現(xiàn)容災(zāi)切換需求树埠;
中間件(RPC糠馆、KV、MQ等):
- RPC:對(duì)于SET服務(wù)怎憋,調(diào)用封閉在SET內(nèi)又碌;對(duì)于非SET服務(wù)九昧,沿用現(xiàn)有的路由邏輯;
- KV:支持SET的數(shù)據(jù)生產(chǎn)和查詢(xún)毕匀;
- MQ:支持分SET的消息生產(chǎn)和消費(fèi)铸鹰;
數(shù)據(jù)同步:
- 全局?jǐn)?shù)據(jù)(數(shù)據(jù)量小且變化不大,比如商家的菜品數(shù)據(jù))部署在中心集群皂岔,其他單元化集群同步全局?jǐn)?shù)據(jù)到本單元化內(nèi)蹋笼;
- 未來(lái)演變?yōu)楫惖囟嗷罴軜?gòu)時(shí),各單元化集群數(shù)據(jù)需要進(jìn)行雙向同步來(lái)實(shí)現(xiàn)容災(zāi)需要
異地容災(zāi):
- 通過(guò)SET化架構(gòu)的流量調(diào)度能力躁垛,將SET分別部署在不同地區(qū)的數(shù)據(jù)中心姓建,實(shí)現(xiàn)跨地區(qū)容災(zāi)支持
高效的本地化服務(wù):
- 利用前端位置信息采集和域名解析策略,將流量路由到最近的SET缤苫,提供最高效的本地化服務(wù)速兔;
- 比如O2O場(chǎng)景天然具有本地生產(chǎn),本地消費(fèi)的特點(diǎn)活玲,更加需要SET化支持
集裝箱擴(kuò)展:
- SET的封裝性支持更靈活的部署擴(kuò)展性涣狗,比如SET一鍵創(chuàng)建/下線(xiàn),SET一鍵發(fā)布等舒憾。
C不是很重要镀钓,所以放到中心集群,需要的時(shí)候去中心集群調(diào)用镀迂,及時(shí)調(diào)用超時(shí)或失敗丁溅,也不影響主流程
SET化架構(gòu)落地原則
對(duì)業(yè)務(wù)透明原則:
- SET化架構(gòu)的實(shí)現(xiàn)對(duì)業(yè)務(wù)代碼透明,業(yè)務(wù)代碼層面不需要關(guān)系SET化規(guī)則探遵,SET的部署等問(wèn)題
SET化切分的規(guī)則:
- 理論上窟赏,切分規(guī)則有業(yè)務(wù)層面按需定制;
- 實(shí)際上箱季,建議優(yōu)先選最大的業(yè)務(wù)維度進(jìn)行切分涯穷;
- 比如海量用戶(hù)的O2O業(yè)務(wù),按用戶(hù)位置信息進(jìn)行切分藏雏。此外接入層拷况、邏輯層和數(shù)據(jù)層可以由獨(dú)立的SET切分規(guī)則,有利于實(shí)現(xiàn)部署和運(yùn)維成本的最優(yōu)化
部署規(guī)范原則:
- 一個(gè)SET并不一定只限制在一個(gè)機(jī)房掘殴,也可以跨機(jī)房或者跨地區(qū)部署赚瘦;為保證靈活性,單個(gè)SET內(nèi)機(jī)器數(shù)不宜過(guò)多(如不超過(guò)1000臺(tái)物理機(jī))奏寨。
RabbitMQ-SET化架構(gòu)實(shí)現(xiàn)
-
SET化消息中間件架構(gòu)實(shí)現(xiàn)(RabbitMQ雙活):
使用RabbitMQ異步消息通信插件 Federation(節(jié)點(diǎn)和節(jié)點(diǎn)起意、集群和集群之間通信) 安裝與配置:
- 安裝插件
rabbitmq-plugins enable rabbitmq_federation
rabbitmq-plugins enable rabbitmq_federation_management
備注
:當(dāng)你再一個(gè)cluster中使用了federation插件,所有在集群中的 nodes都需要安裝federation插件使用RabbitMQ通信插件Rederation:
Federation插件是一個(gè)在不需要cluster進(jìn)行數(shù)據(jù)同步的(選擇一個(gè)cluster中的節(jié)點(diǎn)和另一個(gè)cluster節(jié)點(diǎn)同步)服爷,而brokers之間傳輸消息的高新性能插件杜恰。
Federation插件可以在brokers或者cluster之間傳輸消息获诈,鏈接的雙方可以使用不同的users和virtual hosts、或者雙方的rabbitmq和erlang版本不一致心褐,federation插件使用AMQP協(xié)議通信舔涎,可以接受不連續(xù)的傳輸。
SET化配置規(guī)則:
第一逗爹,F(xiàn)ederation Exchanges亡嫌,可以看成Downstream(82節(jié)點(diǎn))從Upstream(81節(jié)點(diǎn))主動(dòng)拉取消息,并不是拉取所有消息掘而,必須是在Downstream上已經(jīng)明確定義Bindings關(guān)系的Exchange挟冠,也就是有實(shí)際的物理Queue來(lái)接收消息,才會(huì)從Upstream拉取消息到Downstream袍睡。使用AMQP協(xié)議實(shí)施代理間通信知染,Downstream會(huì)將綁定關(guān)系組合在一起,綁定/解綁命令將發(fā)送到Upstream交換機(jī)斑胜。
第二控淡,經(jīng)過(guò)配置后,Upstream節(jié)點(diǎn)已經(jīng)可以把消息直接通過(guò)Federation Exchanges路由給我們的Downstream節(jié)點(diǎn)止潘,然后進(jìn)行消費(fèi)掺炭。
也就是說(shuō)可以實(shí)現(xiàn)消息的轉(zhuǎn)發(fā),接下來(lái)也可以在Upstream添加具體的隊(duì)列去進(jìn)行消費(fèi)Federation Exchanges里的消息凭戴,我們一條消息分別發(fā)送到2個(gè)RabbitMQ集群并且消費(fèi)涧狮,這樣我們可以實(shí)現(xiàn)SET化的關(guān)鍵要素,就是集群間的消息同步了么夫。
- 第三者冤,可以根據(jù)自己的業(yè)務(wù)規(guī)則去規(guī)劃不同的集群去監(jiān)聽(tīng)不同的消息隊(duì)列,從而達(dá)到SET化的手段魏割,保障了性能譬嚣、可靠性、數(shù)據(jù)一致性钞它。
RabbitMQ-基礎(chǔ)組件封裝
MQ組件實(shí)現(xiàn)思路和架構(gòu)設(shè)計(jì)方案
MQ組件需要實(shí)現(xiàn)功能點(diǎn)
- 支持消息高性能序列化轉(zhuǎn)換、異步化發(fā)送消息
- 支持消息生產(chǎn)實(shí)例與消費(fèi)實(shí)例的鏈接池化殊鞭、緩存化遭垛,提升性能
- 支持可靠性投遞消息,保障消息的100%不丟失
- 支持消費(fèi)端的冪等操作操灿,避免消費(fèi)端重復(fù)消費(fèi)的問(wèn)題
- 支持迅速消息發(fā)送模式锯仪,在一些日志收集、統(tǒng)計(jì)分析等需求下可以保證高性能趾盐,超高吞吐量(可忽略100%投遞)
- 支持延遲消息模式庶喜,消息可以延遲發(fā)送小腊,指定延遲時(shí)間,用于某些延遲檢查久窟、服務(wù)限流場(chǎng)景
- 支持事務(wù)消息秩冈,且100%保障可靠性投遞,在金融行業(yè)單筆大金額操作是會(huì)有此類(lèi)需求
- 支持順序消息斥扛,保證消費(fèi)送達(dá)消費(fèi)端的前后順序入问,例如下訂單,再送積分稀颁、優(yōu)惠券等復(fù)合性操作
- 支持消息補(bǔ)償芬失,重試,以及快速定位異常/失敗消息
- 支持集群消息負(fù)載均衡匾灶,保障消息落到具體SET集群的負(fù)責(zé)均衡
- 支持消息路由策略棱烂,指定某些消息路由到指定的SET集群
迅速消息發(fā)送
- 迅速消息是指消息不進(jìn)行落庫(kù)存儲(chǔ),不做可靠性的保障
- 在一些非核心消息阶女、日志數(shù)據(jù)颊糜、或者統(tǒng)計(jì)分析等場(chǎng)景下比較合適
-
迅速消息的特點(diǎn)就是性能最高,吞吐量最大
確認(rèn)消息發(fā)送
- 1张肾、step1芭析,step2:業(yè)務(wù)信息和消息信息入庫(kù)
- 2、step3:消息發(fā)送到MQ Broker
- 3吞瞪、step4:Broker回送一個(gè)ACK確認(rèn)消息
- 4馁启、step5:更新DB中消息狀態(tài)
- 5、step6:定時(shí)任務(wù)讀取中間狀態(tài)消息
- 6芍秆、step7:執(zhí)行消息重發(fā)
- 7惯疙、step8:重發(fā)多次依舊失敗的消息, 將其置為失敗終態(tài)
批量消息發(fā)送
-
批量消息是指我們把消息放到一個(gè)集合里統(tǒng)一進(jìn)行提交,這種方案設(shè)計(jì)思路是期望消息在一個(gè)會(huì)話(huà)里妖啥,比如投擲到threadlocal里的集合霉颠,然后擁有相同會(huì)話(huà)ID,并且?guī)в羞@次提交消息的size等相關(guān)屬性荆虱,最重要的一點(diǎn)是要把這一批消息進(jìn)行合并蒿偎。對(duì)應(yīng)Channel而言,就是發(fā)送一次消息怀读。這種方式希望消費(fèi)端在消費(fèi)的時(shí)候诉位,可以進(jìn)行批量化的消費(fèi),針對(duì)于某一個(gè)原子業(yè)務(wù)的操作去處理菜枷,但是不保障可靠性苍糠,需要進(jìn)行補(bǔ)償機(jī)制
延遲消息發(fā)送
- 延遲消息相對(duì)簡(jiǎn)單,就是我們?cè)贛essage封裝的時(shí)候添加delayTime屬性即可啤誊,使得我們的消息可以進(jìn)行延遲發(fā)送岳瞭,根據(jù)具體的業(yè)務(wù)場(chǎng)景也可以很好的使用得到拥娄。
- 場(chǎng)景舉例:
比如你在電商平臺(tái)買(mǎi)到商品簽收后,不點(diǎn)擊確定支付瞳筏,那么系統(tǒng)自動(dòng)會(huì)在7天(一定時(shí)間)去進(jìn)行支付操作稚瘾。
還要一些自動(dòng)超時(shí)作廢場(chǎng)景,你的優(yōu)惠券/紅包有使用時(shí)間限制乏矾,也可以用延遲消息機(jī)制孟抗。
順序消息發(fā)送
- 順序消息,比較類(lèi)似于批量消息的實(shí)現(xiàn)機(jī)制钻心,但是有些不同凄硼。
- 我們要保障以下幾點(diǎn):
1、發(fā)送的順序消息捷沸,必須保障消息投遞到同一個(gè)隊(duì)列摊沉,且這個(gè)消費(fèi)者只能有一個(gè)(獨(dú)占模式)
2、然后需要統(tǒng)一提交(可能合并成一個(gè)大消息痒给,也可能拆分成多個(gè)消息)说墨,并且所有消息的會(huì)話(huà)ID一致。
3苍柏、添加消息屬性:順序標(biāo)記的序號(hào)尼斧、和本次順序消息的SIZE屬性,進(jìn)行落庫(kù)操作试吁。
4棺棵、并行進(jìn)行發(fā)送給自身的延遲消息(注意帶上關(guān)鍵屬性:會(huì)話(huà)ID、SIZE)進(jìn)行后續(xù)處理消費(fèi)(接收到第一個(gè)消息后熄捍,創(chuàng)建延遲消息隊(duì)列烛恤,等幾分鐘后,所有的順序消息都落庫(kù)后)
5余耽、當(dāng)收到延遲消息后缚柏,根據(jù)會(huì)話(huà)ID、SIZE抽取數(shù)據(jù)庫(kù)數(shù)據(jù)進(jìn)行處理即可碟贾。
6币喧、定時(shí)輪詢(xún)補(bǔ)償機(jī)制,對(duì)于異常情況
備注:比如生產(chǎn)端消息沒(méi)有完全投遞成功袱耽,或者消費(fèi)端落庫(kù)異常導(dǎo)致消費(fèi)端落庫(kù)缺少消息條目的情況
事務(wù)消息發(fā)送
- 事務(wù)消息粱锐,相對(duì)使用比較少見(jiàn),但是在互聯(lián)網(wǎng)行業(yè)中扛邑,面對(duì)單筆大額現(xiàn)金流交易時(shí)遇到遇到過(guò):比如單筆轉(zhuǎn)賬超過(guò)一個(gè)上限的時(shí)候,我們就希望這個(gè)消息優(yōu)先級(jí)最高铐然,并且可靠性要求達(dá)到100%蔬崩,當(dāng)然我們的系統(tǒng)和銀行端系統(tǒng)都要兼顧才行恶座,所有也會(huì)有一些補(bǔ)償機(jī)制,主動(dòng)發(fā)起銀行端查詢(xún)指令機(jī)制等沥阳。
- 為了保障性能的同時(shí)跨琳,也支持事務(wù)。我們并沒(méi)有選擇傳統(tǒng)的RabbitMQ事務(wù)和Spring集成的機(jī)制桐罕,因?yàn)樵谛阅軠y(cè)試過(guò)程中脉让,效果并不理想,非常消耗系統(tǒng)資源且會(huì)出現(xiàn)阻塞等情況功炮,在高峰期也是一定程度上影響MQ集群的性能
- 解決方案:
我們采用類(lèi)似可靠性投遞的機(jī)制溅潜,也就是補(bǔ)償機(jī)制。
但是我們的數(shù)據(jù)源必須是同一個(gè)薪伏,也就是業(yè)務(wù)操作DB1數(shù)據(jù)和消息記錄BD2數(shù)據(jù)庫(kù)必須使用同一個(gè)數(shù)據(jù)源
然后利用重寫(xiě)Spring DatasourceTransactionManage滚澜,在本地事務(wù)提交的時(shí)候進(jìn)行發(fā)送消息,但是也有可能事務(wù)提交成功但是消息發(fā)送失敗嫁怀,這個(gè)時(shí)候就需要進(jìn)行補(bǔ)償了设捐。
-
DatasourceTransactionManager核心代碼:
消息冪等性保障-消息路由規(guī)則架構(gòu)設(shè)計(jì)
消息冪等性的重要性
- 保障消息的冪等性,這也是我們?cè)谑褂肕Q中至關(guān)重要的環(huán)節(jié)
- 可能導(dǎo)致消息出現(xiàn)非冪等性的原因:
1塘淑、可靠性消息投遞機(jī)制(消息失敗時(shí)多次發(fā)送)
2萝招、MQ Broker服務(wù)與消費(fèi)端傳輸消息過(guò)程中出現(xiàn)網(wǎng)絡(luò)抖動(dòng)
3、消費(fèi)端的故障或異常
以上這些問(wèn)題都會(huì)導(dǎo)致消費(fèi)端重復(fù)消息問(wèn)題存捺。
參考:
http://www.reibang.com/p/4dc45fc5936c
https://blog.csdn.net/love905661433/article/details/85452115
http://www.reibang.com/p/a1bb3e1eba87