無法做單元化,異地雙活也可以玩得很溜
?一、基本概念
1、機(jī)房
中心機(jī)房
當(dāng)前單機(jī)房情況下的機(jī)房,除了雙活的業(yè)務(wù)外,長尾業(yè)務(wù)以及沒做多活的業(yè)務(wù)都在該機(jī)房。
- 單元機(jī)房
新機(jī)房,即雙活新增的機(jī)房,用以承接主鏈路雙活能力流量的機(jī)房。
2、路由
sharding_id即route_code,雙活根據(jù)路由規(guī)則會轉(zhuǎn)換為route_code(四輪出行為地域)。每個route_code會對應(yīng)中心機(jī)房或者單元機(jī)房。網(wǎng)關(guān)、soa、redis、db等都會根據(jù)route_code路由到正確的機(jī)房。
二、多活的幾種模式
1、同城雙活
在同個城市進(jìn)行雙活部署(兩個IDC)。
2、異地雙活
在兩個城市進(jìn)行雙活部署(每個城市一個IDC)。
3、異地多活
在多個城市進(jìn)行多IDC部署。
4、優(yōu)劣勢
三、單元化
大家可以考慮一個問題,一個公司,或者某個業(yè)務(wù)在tps達(dá)到幾十萬或者幾百萬在整個系統(tǒng)設(shè)計(jì)、架構(gòu)乃至機(jī)房瓶頸就會顯得極為突出。但是放眼整個國家或者全球來看,全部的tps何止百萬、千萬,歸根結(jié)底還是因?yàn)椴煌牧髁?,在最開始就根據(jù)公司、業(yè)務(wù)、機(jī)房、地區(qū)路由到了不同的機(jī)房,而由于公司、業(yè)務(wù)之間天然是隔離的,因此每個公司的每個業(yè)務(wù)只需要處理自己的這部分tps就行。如:淘寶流量只會在阿里的應(yīng)用、機(jī)房,滴滴的流量只會在滴滴的應(yīng)用、機(jī)房。但是假如某個公司的某個業(yè)務(wù)的tps有一億,假如無法做到水平無限擴(kuò)容,必然是沒有公司能夠抗住這么大的并發(fā)的,不光是架構(gòu),即使物理機(jī)房也不允許這么大的集群(電力、場地都會有限制)。而單元化提供了理論上無限水平擴(kuò)容的架構(gòu)能力。
單元化可以理解為異地多活的最終形態(tài)。單元化在流量入口將流量拆分到不同的IDC,每個IDC分別承接自己的流量,且IDC之前的流量不會互相調(diào)用。單元化和區(qū)域無關(guān),理論上做到單元化后,新增的流量完全可以新增IDC解決,而新增的IDC不會受到區(qū)域的限制,因?yàn)镮DC之前不會有流量互相調(diào)用。
判斷是否做到單元化,我理解只要一個標(biāo)準(zhǔn),即是否流量能夠自閉環(huán)。舉個例子,如果你的A機(jī)房在上海部署,B機(jī)房很遠(yuǎn)的海外的任意一個地方,對業(yè)務(wù)也毫無影響(AB機(jī)房地域距離很長,如果無法做到自閉環(huán),則相互調(diào)用的RT會變長,必然影響業(yè)務(wù)),那么你就可以認(rèn)為是單元化成功了。
單元化流量如下:
單元化做雙活只需要在底層的數(shù)據(jù)層面進(jìn)行同步即可。如下所示:
四、雙活的流量路由規(guī)則
1、路由方式
1)隨機(jī)路由
將流量按照比例隨機(jī)路由到各自IDC,只需按照比例路由到每個IDC,而無任何規(guī)則。故障情況下,可以將該故障機(jī)房的流量切換到另外的IDC。
2)用戶id路由
根據(jù)用戶id將流量按照一定比例路由到各自IDC,每個用戶的操作都會路由到指定的IDC。故障情況下,可以將該故障機(jī)房的流量按照用戶切換到另外的IDC。
3)地域路由
按照用戶所屬城市將流量按照一定比例路由到各自的IDC,每個地方的用戶操作都會路由到指定的IDC。故障情況下,可以將該故障機(jī)房的流量地域切換到另外的IDC。
2、四輪出行的選擇
經(jīng)過多番討論,哈啰四輪出行最終選擇了按照地域路由。
主要理由如下:隨機(jī)路由在各類多活設(shè)計(jì)中都不算一個好的方案,主要原因是隨機(jī)路由由于其無規(guī)律性,在多活項(xiàng)目中,無法做到單元化。選擇地域路由而非用戶維度路由,主要是由于四輪業(yè)務(wù)和電商業(yè)務(wù)存在一些區(qū)別,在電商業(yè)務(wù)中的基本操作都是基于C端用戶,每個C端用戶只操作自己的訂單數(shù)據(jù),因此訂單數(shù)據(jù)按照用戶id天然是隔離的,單元化也比較好做,但是此方案也是犧牲了B端的商家的體驗(yàn),商家操作多用戶訂單數(shù)據(jù)必然會存在跨機(jī)房的可能性,從而影響商家體驗(yàn)。
作為四輪來說,買家和賣家分別為乘客和司機(jī),是天然的雙訂單模型(司機(jī)訂單和乘客訂單),因此如果用用戶id路由,則在同時操作司機(jī)訂單和乘客的接口(如司機(jī)接單)中,必然會存在大量的跨機(jī)房路由(司機(jī)和乘客因?yàn)橛脩鬷d不同分到不同的機(jī)房)。而如果按照地域來分,則由于出行訂單跨城或者跨省的概率極低,因此該跨機(jī)房率會大大降低,且可以根據(jù)實(shí)際跨機(jī)房單量比例去人為降低跨機(jī)房數(shù)量。但是該方案也有一定缺陷,因?yàn)榈赜蛴唵螘诓煌臅r間和場景下,如:節(jié)假日、下雨天等會存在比較大的流量波動,導(dǎo)致同城、同省流量波動較大,從而導(dǎo)致機(jī)房壓力大小不一致。
五、雙活方案
1、中間方案
雙活中間件提供的能力主要分為四類,存儲、消息、soa和雪花算法。
2、存儲
存儲提供的能力大部分為底層的數(shù)據(jù)雙向同步。
redis的跨機(jī)房讀寫和跨機(jī)房加鎖均是因?yàn)殡p訂單模型無法做到單元化,提供的雙活能力。
redis雙寫則為無雙向同步能力時的臨時能力。
db糾偏則是db層面指定路由,也是為了兜底,當(dāng)soa路由出異常,在db層做最后的兜底(可訪問跨機(jī)房數(shù)據(jù))。
db禁寫保護(hù)則是當(dāng)業(yè)務(wù)開啟禁寫保護(hù),非本機(jī)房的訂單無法在本訂單操作,也是db兜底保護(hù)的一種。
3、消息
消息則分為發(fā)送和消費(fèi)。
對于發(fā)送來說,單元到中心的復(fù)制和中心到單元的復(fù)制,則都是一個機(jī)房消息復(fù)制到另外機(jī)房,也是無法單元化的一種解決方案。當(dāng)然該方案也可以兼容雙活應(yīng)用發(fā)送消息和非雙活應(yīng)用消費(fèi)者的問題。
消費(fèi)本機(jī)房:只能消費(fèi)本機(jī)房產(chǎn)生的消息,異地機(jī)房的復(fù)制消息無法消費(fèi)。
都不消費(fèi):代表本機(jī)房和異地機(jī)房都不消費(fèi)。
消費(fèi)本機(jī)房和異地機(jī)房消息,則代表消息消費(fèi)本機(jī)房和異地機(jī)房消息(消費(fèi)雙份消息)。
4、soa
soa接口需要根據(jù)特定的條件將rpc請求路由到正常的機(jī)房。
服務(wù)提供方路由則表示該路由規(guī)則由服務(wù)提供方指定。
服務(wù)消費(fèi)方路由則表示該路由規(guī)則由服務(wù)消費(fèi)方指定。
5、雪花算法
雙活由于zk集群是兩個機(jī)房的,需要在雪花算法上打上機(jī)房標(biāo)識,保證全局唯一。
6、業(yè)務(wù)改造
業(yè)務(wù)改造大部分是基于中間件方案的改造。而其中的部分方案是基于業(yè)務(wù)自己述求進(jìn)行的一些雙活改造點(diǎn)。
1)單元化改造
部分業(yè)務(wù)邏輯之前在單機(jī)房情況下無法做到單元化,需要對部分可單元化的業(yè)務(wù)進(jìn)行改造。
2)db緩存一致性
基于訂單可靠性保證,對訂單數(shù)據(jù)通過binlog消息保障兩機(jī)房數(shù)據(jù)一致性。
3)機(jī)房過濾改造
基于機(jī)房信息,處理非本機(jī)房邏輯,或者過濾非本機(jī)房邏輯(目前無法單元化的臨時方案)。
4)單號改造
發(fā)單的時候需要將路由規(guī)則打到訂單號上,在修改訂單其他屬性時根據(jù)訂單號進(jìn)行路由(保障單元化)。?