當前位置:
首頁 > 最新 > 異地雙活實踐筆記

異地雙活實踐筆記

最近恰好在搞異地雙活,以下是一個梳理:

基本概念

1、異地容災。這僅僅是一個冷備的概念。也就是在平時正常的時候,另外一個機房只是當做備份。

2、異地雙(多)活。而異地雙(多)活,卻是指有兩個或者多個可以同時對外服務的節點,任意一個點掛了,也可以迅速切換到其他節點對外服務,節點之間的數據做到准實時同步。

分類

根據是否需要數據同步大體分為三類:

1、必須同步型。(比如資料庫)

2、無須同步型。比如緩存,僅僅是當做緩存,就可以這樣做(這個有待商榷,其實緩存也需要同步的,嚴格來說的話)。

3、只能單活(對全局原子要求較高),不接受有一定時延的「不一致」窗口。

核心問題

數據同步、網路時延。

切換方式

1、自動切換。自動切換表現為當災難來臨時,程序內部可以自動識別出問題然後切換至可用機房。

2、手動切換。通過簡單的配置,在幾分鐘或者一兩小時內切換到另外的機房。

異地多活面臨的挑戰

1、切換問題。

切換問題不僅僅是災難發生自動切換到好的機房,還有另外一個問題,就是災難機房恢復能力後,如何再切換回去,切換回去的數據同步問題又是需要解決的。

2、跨機房流量問題。

跨機房的流量是花錢的。所以不是無限大的。控制跨機房消息體大小,越小越好。然而,很多時候要想保證數據同步是一件很耗費流量的事情。但跨機房流量真的是一座山。

既然跨機房流量有限制,而且不穩定。所以有一種解決方案就是不跨機房。既然不跨機房就要做用戶分區,確保每個用戶只能訪問自己所在的區,這樣至少能保證該用戶自己的數據的完整。

3、所有的業務都適合做異地雙活嗎?

異地多活效果看起來很誘人,但如果不假思索貪大求全的要求所有業務都實現異地多活的話,就會把自己帶到坑裡去。

第一個原因是異地多活是有成本的,包括開發成本和維護成本。需要實現異地多活的業務越多,方案越複雜,投入的設計開發時間越多;同時維護成本也會越高,需要更多的機器,需要更多的帶寬。

第二個原因是有的業務理論上就無法實現異地多活。典型的有「餘額」和「庫存」這兩個業務。

以餘額為例,假設我們實現了餘額的異地多活業務,用戶小明有10000塊錢,在A機房給女友轉賬了5000塊,還剩餘5000塊;如果此時A機房異常且數據還沒同步到B機房,小明登錄到B機房發現自己又有10000塊了,小明感覺中彩票了,趕緊又轉了10000塊給女友,最後出現了小明只有10000塊卻轉賬了15000塊的問題,對於和資金相關的業務,這樣的問題是絕對無法容忍的,哪怕一個用戶有問題都不行。

所以,異地多活也不能保證所有業務都異地多活,在設計異地多活方案的時候,需要從業務和用戶的角度出發,識別出核心和關鍵業務,明確哪些業務是必須實現異地多活,哪些是可以不實現異地多活,哪些是不能實現異地多活的。比如「登錄」必須實現異地多活、「註冊」和「修改用戶信息」不一定要實現異地多活。

4、冷備還是熱備。冷備了以後,一直冷備,當真正出現問題,你還有勇氣去切換到那個一直冷的機房嗎?恐怕需要點勇氣。

5、數據一致性問題。

解決方案:

(1)、守護進程同步。

(2)、客戶端雙寫。

(3)、不去解決。不需要解決的前提是用戶分區。分區後,從本質上說,其實是沒有做到雙活的。只是看起來一個業務確實被分到了多個機房而已。

6、讀取問題。

這個相對來說要好解決一些,就是就近讀取。

業務以及基礎組件異地雙活方案

業務實例異地雙活

業務實例的異地雙活。這個相對來說要簡單一些,只要做到無狀態,再如果通過docker這些容器結束,基本上是相對來說容易一些。

消息隊列的異地雙活

rabbitmq 每個機房部署一套server,然後每個機房的業務使用各自機房的mq。通過haproxy自動映射到本機房的broker。topic同步,通過rest api讀取到

配置文件,然後同步到另外一個機房的rabbitmq下。

具體restapi:

http://17X.XXX.X.XXX:15672/api/definitions

以上只是同步了rabbitmq的元數據,而且是全量同步。

消息同步問題:如果不同步會導致消息丟失。所以mq消息其實也是需要同步的。

同步可以通過客戶端雙寫,或者服務端複製。雙寫更加容易。

Redis的異地雙活

Redis 的異地雙活。就是分別在每個機房搭建一套Redis集群。 然後每個機房的業務都去訪問各自機房的Redis集群。

但這樣只是能保證基本的緩存能力。如果業務中涉及到一些全局的原子操作,那麼這樣的做法顯然不能滿足需求。

原因很簡單,比如你使用redis incr自增命令:

a 機房 加1 後變為了1,b機房的業務也加1, 本來應該是2。結果由於各自都是訪問了自己的redis,所以全局計數顯然是有問題的。

怎麼解決呢?就需要涉及到全局操作的業務,去單獨的連接 一個全局的唯一的那個 redis集群,這個redis集群專門用於 業務的全局操作。

但這樣的後果,就是會涉及到跨機房流量問題,因為這個全局的redis集群無論放在哪個機房,另外一個機房的業務要想訪問都得跨機房。

讀取流程:

寫入流程:

全局操作:

資料庫的異地雙活

canal:

早期,阿里巴巴B2B公司因為存在杭州和美國雙機房部署,存在跨機房同步的業務需求。不過早期的資料庫同步業務,主要是基於trigger的方式獲取增量變更,不過從2010年開始,阿里系公司開始逐步的嘗試基於資料庫的日誌解析,獲取增量變更進行同步,由此衍生出了增量訂閱&消費的業務,從此開啟了一段新紀元。

基於日誌增量訂閱&消費支持的業務:

資料庫鏡像

資料庫實時備份

多級索引 (賣家和買家各自分庫索引)

search build

業務cache刷新

價格變化等重要業務消息

otter:

阿里巴巴B2B公司,因為業務的特性,賣家主要集中在國內,買家主要集中在國外,所以衍生出了杭州和美國異地機房的需求,同時為了提升用戶體驗,整個機房的架構為雙A,兩邊均可寫,由此誕生了otter這樣一個產品。

otter第一版本可追溯到04~05年,此次外部開源的版本為第4版,開發時間從2011年7月份一直持續到現在,目前阿里巴巴B2B內部的本地/異地機房的同步需求基本全上了otter4。

目前同步規模:

同步數據量6億

文件同步1.5TB(2000w張圖片)

涉及200+個資料庫實例之間的同步

80+台機器的集群規模

說明:

a. 數據涉及網路傳輸,S/E/T/L幾個階段會分散在2個或者更多Node節點上,多個Node之間通過zookeeper進行協同工作 (一般是Select和Extract在一個機房的Node,Transform/Load落在另一個機房的Node)

b. node節點可以有failover / loadBalancer. (每個機房的Node節點,都可以是集群,一台或者多台機器)

Zookeeper異地雙活

先來點背景知識:

1、zookeeper中的server機器之間會組成leader/follower集群,1:n的關係。採用了paxos一致性演算法保證了數據的一致性,就是leader/follower會採用通訊的方式進行投票來實現paxos。

2、zookeeper還支持一種observer模式,提供只讀服務不參與投票,提升系統。

異地多活決定了我們需要進行跨機房操作,比如杭州,美國,香港,青島等多個機房之間進行數據交互。

跨機房之間對應的網路延遲都比較大,比如中美機房走海底光纜有ping操作200ms的延遲,杭州和青島機房有70ms的延遲。

為了提升系統的網路性能,在部署zookeeper網路時會在每個機房部署節點,多個機房之間再組成一個大的網路保證數據一致性。(zookeeper千萬別再搞多個集群)。

最後的部署結構就會是:

杭州機房 >=3台 (構建leader/follower的zk集群)

青島機房 >=1台 (構建observer的zk集群)

美國機房 >=1台 (構建observer的zk集群)

香港機房 >=1台 (構建observer的zk集群)

一句話概括就是: 在單個機房內組成一個投票集群,外圍的機房都會是一個observer集群和投票集群進行數據交互。 這樣部署的一些好處,大家可以細細體會一下。

針對這樣的部署結構,我們就可以實現就近訪問: 比如在美國機房的機器就去優先訪問本機房的zk集群,訪問不到後才去訪問杭州機房。

默認在zookeeper3.3.3的實現中,認為所有的節點都是對等的。並沒有對應的優先集群的概念,單個機器也沒有對應的優先順序的概念。

擴展代碼:(比較暴力,採用反射的方式改變了zk client的集群列表)

先使用美國機房的集群ip初始化一次zk client

通過反射方式,強制在初始化後的zk client中的server列表中又加入杭州機房的機器列表

Java代碼

ZooKeeperzk=null;

try{

zk =newZooKeeper(cluster1,sessionTimeout, newAsyncWatcher() {

public voidasyncProcess(WatchedEvent event) {

//do nothing

}

});

if(serveraddrs.size() >1) {

// 強制的聲明accessible

ReflectionUtils.makeAccessible(clientCnxnField);

ReflectionUtils.makeAccessible(serverAddrsField);

// 添加第二組集群列表

for(inti =1;i

String cluster = serveraddrs.get(i);

// 強制獲取zk中的地址信息

ClientCnxn cnxn = (ClientCnxn) ReflectionUtils.getField(clientCnxnField,zk);

List serverAddrs = (List) ReflectionUtils

.getField(serverAddrsField,cnxn);

// 添加第二組集群列表

serverAddrs.addAll(buildServerAddrs(cluster));

}

}

}

異地雙活思維誤區

非同步雙活思維誤區:

1、所有業務異地多活!

2、實時一致性。我要所有數據都同步!

3、只使用存儲系統的同步功能!

4、我要保證業務100%可用!

5、所有用戶異地多活

一句話談「異地多活」

綜合前面的分析,異地多活設計的理念可以總結為一句話:採用多種手段,保證絕大部分用戶的核心業務異地多活

選型時需要考慮的維度

以下是方案選型時需要考慮的一些維度:

能否整業務遷移:如果機器資源不足,建議優先將一些體系獨立的服務整體遷移,這樣可以為核心服務節省出大量的機架資源。如果這樣之後,機架資源仍然不足,再做異地多活部署。

服務關聯是否複雜:如果服務關聯比較簡單,則單元化、基於跨機房消息同步的解決方案都可以採用。不管哪種方式,關聯的服務也都要做異地多活部署,以確保各個機房對關聯業務的請求都落在本機房內。

是否方便對用戶分區:比如很多遊戲類、郵箱類服務,由於用戶可以很方便地分區,就非常適合單元化,而SNS類的產品因為關係公用等問題不太適合單元化。

謹慎挑選第二機房:盡量挑選離主機房較近(網路延時在10ms以內)且專線質量好的機房做第二中心。這樣大多數的小服務依賴問題都可以簡化掉,可以集中精力處理核心業務的異地多活問題。同時,專線的成本佔比也比較小。以北京為例,做異地多活建議選擇天津、內蒙古、山西等地的機房。

控制部署規模:在數據層自身支持跨機房服務之前,不建議部署超過兩個的機房。因為異地兩個機房,異地容災的目的已經達成,且伺服器規模足夠大,各種配套的設施也會比較健全,運維成本也相對可控。當擴展到三個點之後,新機房基礎設施磨合、運維決策的成本等都會大幅增加。

消息同步服務化:建議擴展各自的消息服務,從中間件或者服務層面直接支持跨機房消息同步,將消息體大小控制在10k以下,跨機房消息同步的性能和成本都比較可控。機房間的數據一致性只通過消息同步服務解決,機房內部解決緩存等與消息的一致性問題。跨機房消息同步的核心點在於消息不能丟,微博由於使用的是MCQ,通過本地寫遠程讀的方式,可以很方便的實現高效穩定的跨機房消息同步。

人們的總結以及經驗

1 、如果業務量不大,沒必要做異地多活,因為異地多活需要的運維資源成本、開發成本都非常高;

2 、注意機房間的延時問題,延時大的可能達到100ms以上,如果業務需要多次跨機房請求應用的話,延遲的問題會徹底放大;

3 、跨機房的專線很大概率會出問題,要做好運維或者程序層面的容錯;

4 、不能依賴MySQL雙寫,必須有適應自身業務的跨機房消息同步方案;

5 、MySQL或者其他存儲的數據同步問題,在高延時和較差的網路質量的情況下,考慮如何保證同步質量;

6、 考慮使用docker等容器虛擬化技術,提高動態調度能力;

7、Devops流程配套。devops要支持推送到兩個機房。

真實的異地雙活案例

真實的異地雙活案例:

5.27日下午17時許,支付寶被反映故障;18時許,支付寶通過官方微博給出回應,解釋是因為電信運營商光纖被挖斷。19時許,支付寶服務恢復正常。22時許,支付寶官方微博正式回應復原了整個事件。

圍繞整個事件有很多討論,討論的中心最主要的有兩點:「為什麼光纖被挖斷,會造成整個機房癱瘓」、「為什麼支付寶的業務恢復用了兩個小時」。

其中,第一個問題,應該是電信運營商的光纖災備出現問題。第二個焦點問題「為什麼支付寶用了2個小時恢復了業務」,一堆所謂「業內人士」眾說紛紜。其實,這應該是中國金融史上,首次完全意義的災難成功切換案例。

在此之前,中國金融行業投入重金建設的災備系統基本上有這麼兩類用武之地(一般來說,增建一個災備數據中心的建設成本是單數據中心成本的1.1-1.2倍):

1,計劃內災備切換演習,全副武裝、如臨大敵、不開一槍、全身而退。

2,因系統升級造成的被動災備切換。

例如2013年鬧得沸沸揚揚的某行DB2升級造成的系統回滾切換。萬幸的是,這是發生在凌晨的系統升級故障,當時沒有實時交易發生;某行也準備了各種應急預案,只是恢復的時間超出了計劃,網點推遲了一個小時開業而已;而另一家西部的區域銀行就沒有這麼強的科技實力了,同樣是DB2升級失敗,系統恢復時間用了37小時40分鐘(37小時啊,吼吼,坐火車都到莫斯科了)

像支付寶這種突發情形下的災備切換還真是頭一遭,而且居然成功了。支付寶雖然運氣差了點,但技術能力還真不是一般金融機構能拼的。

在支付寶微博答覆中,有一個新名詞——「異地多活」。在傳統了災備方案中,一般提的都是同城災備、異地災備、兩地三中心。與傳統的災備技術相比,異地多活的特點是:在不同地點的數據中心都可以同時支持業務,而且每個地點發生的交易都是真實業務流量,而不是常見的一主一備,如果主中心沒有問題,備份中心永遠都是「備胎」。

這種多活數據中心的好處是:因為所有的數據中心都在支持交易,所以能節約IT成本;另外傳統方式中備份系統都不在真實的交易活動狀態,所以很難判斷它的狀態到底怎麼樣,在出現問題時,都不一定敢切過去。

大規模的「異地多活」,據說目前全球除了阿里能做到,也就Google和Facebook實現了,還是非金融類的業務。中國銀行業,只有某國有大行在去年6月份實現了上海同城兩個數據中心的雙活,是「同城雙活」,還沒有實現「異地多活」,而且在災難真正發生時,切換效果如何,還有待驗證。

昨天是支付寶「異地雙活」第一次真刀實槍的上戰場,支付寶因為要滿足金融行業的很多要求,特別是對交易一致性、數據完整性等方面的要求,目前還處於小範圍試用階段,沒有全體上線,例如昨天杭州機房癱瘓後,有一部分流量跑在支付寶異地機房。因此,在昨天支付寶2小時整體恢復之前,並不是所有交易都停止的,並且基於「異地多活」技術,實現了這部分用戶的無感知切換。

對另外沒有通過「異地多活」技術切換的交易流量,支付寶選擇了最穩妥的做法:首先進行了完整的數據校驗,保證所有客戶的客戶信息、賬戶信息、資金信息、交易信息都是正確的,一切確認完成後,才重新「開門迎客」。這個過程耗時了一個多小時,不過相比較支付寶數億客戶所對應的校對數據量,這個時間還是可以接受的。

側面印證切換效果的是:被挖斷的光纖修到半夜才恢復,而支付寶的業務在晚間19點多恢復正常。

客觀來講,支付寶的這次表現,是一次說不上完美、但很成功的真實災難切換,也是中國金融史上第一次在完全突發情形下,成功完成切換的真實案例。整個切換過程中,沒有一條客戶數據丟失,也體現了金融級的數據高可用要求,雖然切換的時間對用戶來說長了點,但「就像是一次跳水,整體完成的質量很高,只是落水時水花沒有壓好,水花稍微大了點。」

估計經過這次折騰,支付寶全盤推進「異地多活」的速度會加快,可能在今年七八月份實現。

部分內容整理自網路

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 ImportSource 的精彩文章:

TAG:ImportSource |

您可能感興趣

虢國飛:餓了么異地雙活資料庫實戰
億級用戶、跨千公里數據中心異地雙活的實踐
華為存儲雙活解決方案 助力金融行業核心業務
災備演練是「雙活」容災做好的前提
做容災,雙活、多活、同城、異地、多雲,到底應該怎麼選?
烏龜意外被截去前肢,主人為它做了雙活動自如腿,走起路都帶風
存儲雙活讓數據更安全
神秘燈籠與幸運召喚師 雙活動與你共賀元宵
雙活距離太遠為啥用波分,容災鏈路設計關鍵點知多少?
雙活太遠為啥用波分,容災鏈路設計關鍵點知多少?
DB2資料庫雙活方案設計要點
孕婦多次產檢雙活胎卻只分娩一胎 醫院稱誤查 警方衛計介入調查
孕婦多次產檢雙活胎卻只分娩一胎 醫院稱誤查 警方衛計部門介入調查
孕婦多次產檢雙活胎卻只分娩一胎 醫院稱誤查 警方等部門介入
孩子去哪了?孕婦產檢都說是雙活胎結果只生下一胎 醫院:是誤查
歲月並沒有在她們身上留下過多的痕迹,到底她們是如何保鮮的呢?雙雙活出了18歲
紅漆皮奪目加持!又一雙活力 Air Max 97 登場!
華為SAN+NAS雙活解決方案助華龍網新聞發布
Keepalived LVS-DR單網路雙活雙主配置模式
NASA擬利用雙活動發射平台增加SLS Block1型任務