更多相關(guān)文章閱讀
作者簡介:
我今天分享是餓了么在數(shù)據(jù)庫和多活數(shù)據(jù)庫這塊的實戰(zhàn)經(jīng)歷,供大家參考。 主要分享以下五點: 1、多活當(dāng)中的難點 2、多活的架構(gòu) 3、數(shù)據(jù)庫改造 4、DBA 挑戰(zhàn) 5、收益與展望 一、多活當(dāng)中的難點我們先來看一下多活的第一個難點:要考慮做多活到底是同城的多活還是異地的多活,跨地域網(wǎng)絡(luò)延時是現(xiàn)階段很難突破的點,因為餓了么面臨的是異地的多活,所以我們需要基于延時這個前提來考慮方案。 從北京到上海中間有30毫秒的延遲,這個會帶來什么問題?我們接下來會講。 上圖是同城和異地多活不同的點,復(fù)雜性和可拓展性對架構(gòu)的影響方面會有很大的不同。 我們挑幾個點講一下: 1、如果只是做同城多活的話,像30毫秒的延時不需要考慮,因為同城的延時通常只有幾毫秒,跟同機房差不大。 2、如果是異地30毫秒的延時就需要重點考慮了,因為如果是反復(fù)調(diào)用的應(yīng)用,放大的時間就不只是30毫秒了,可能是300毫秒、500毫秒,對很多應(yīng)用來說是不可接受的。 在可擴展性方面如果做的是異地多活的話,你的可擴展性理論上來說沒有太多的邊界。我們做同城多活只能在上海機房里面選,如果是異地多活,可能是全國甚至是全球都可以選。 還有一個比較難的問題,就是怎么保證數(shù)據(jù)的安全。多活數(shù)據(jù)可能面臨多個寫入點,可能會錯亂、會沖突、循環(huán)復(fù)制、數(shù)據(jù)環(huán)路等問題,這種情況下怎么保障一致性。如果這些沒有考慮好之前,你是不能上多活方案的,多點寫入的風(fēng)險對數(shù)據(jù)的考驗是很大的。 綜合考慮下來我們選擇了異地多活,所以這些問題我們都需要克服,也意味著會面臨很多的改造。 如何解決跨機房延時對業(yè)務(wù)的影響,包括各種抖動甚至是斷網(wǎng)的問題。怎樣有效區(qū)分我們訪問的流量,最大限度地保障用戶的訪問落在正確的機房,這個都是需要解決的難點。 我們采取了一些措施: 1、盡量把業(yè)務(wù)做成類聚的,讓一個用戶的訪問落在同一個地方。 2、不是所有的業(yè)務(wù)都有多活特性的,還可以有全局使用的業(yè)務(wù)(比方用戶數(shù)據(jù)),所以需要做業(yè)務(wù)類型劃分。
二、多活的架構(gòu)粗略過了多活的一些難點和我們的應(yīng)對方案后,我們現(xiàn)在來看一下整個多活的架構(gòu)。這個上面是我們從入口流量、分流控制、數(shù)據(jù)多機房同步,包括各個重要組件的架構(gòu)等。還有里面有g(shù)lobol zone這一項,它是我們剛剛講的需要全局依賴的業(yè)務(wù)會把它放在globol zone里面。 DRC這是做多活時相當(dāng)重要的組件,主要解決數(shù)據(jù)在多個機房當(dāng)中的同步復(fù)制。我們從北京機房寫入的數(shù)據(jù),會同步到上海的機房。上海的機房寫入的數(shù)據(jù)也會通過DRC這個組件同步到北京的機房。大家可以看它其實包含三塊服務(wù),Replicator、Applier和Manager,一個收集變更數(shù)據(jù)、一個將變更數(shù)據(jù)寫入到另一個機房,另外一個是做管理控制。 DB架構(gòu)這塊我們有兩類(準(zhǔn)確講還有一類是多推的,比較少),第一類是ShardingZone,不管是數(shù)據(jù)寫入還是訪問都是本機房提供,出問題的時候也只是流量的切換,并不涉及到底層的變動,這個是真正多活的架構(gòu)。 還有一種是剛剛講的,有些沒有辦法做業(yè)務(wù)分區(qū)的,是globolZone的架構(gòu),寫是集中在一個機房,讀在本地機房完成。大家可能會想到globalzone這種架構(gòu)會天然面臨一些剛剛講的數(shù)據(jù)延遲的問題,所以這塊我們的定義是一些寫入量不大,訪問量大,對數(shù)據(jù)延時是不那么敏感的業(yè)務(wù)就可以放到這里面來。 三、數(shù)據(jù)庫改造多活項目我們調(diào)研大概花的時間有半年左右,但真正做改造的時候時間是相當(dāng)短的。從啟動這個項目到真正上線就用了三個月左右的時間。那時候時間是相當(dāng)緊的,大家可以看一下我列舉大的為配合多活數(shù)據(jù)庫所做的改造項目。 首先面臨的問題,就是我們要把數(shù)據(jù)全量的從一個機房導(dǎo)入到另外一個機房,這個不光有測試環(huán)境還有生產(chǎn)環(huán)境都要全量的同步。我們數(shù)據(jù)有幾百T數(shù)據(jù),幾百套集群,有各種主從結(jié)構(gòu)需要搭建需要去搭起來,每個節(jié)點時間也很短。 我們剛剛講的DRC會做數(shù)據(jù)的同步,但同步的時候也會面臨數(shù)據(jù)沖突的問題,為解決這個問題我們需要在所有表上增加一個DRC時間戳字段,用來判斷哪一邊數(shù)據(jù)是最新的,這樣在數(shù)據(jù)發(fā)生沖突的時候,我們會選最新的數(shù)據(jù)作為最終的數(shù)據(jù)。 為防止多活主鍵沖突,數(shù)據(jù)庫做了一些自增的調(diào)整,自增步長放大后馬上就會面臨數(shù)據(jù)溢出的問題,所以我們需要把主鍵都從int調(diào)整為bigint。主鍵改完以后還有一些外鍵依賴的也會需要改造,所以整體會要做很多的DDL(幾乎是全量表),而在MySQL里面DDL其實是風(fēng)險比較高的操作。 第二個大改造是因為區(qū)分了不同的業(yè)務(wù)類型(我們剛剛講了有g(shù)oloblZone這些),就會面臨各種不同類型的業(yè)務(wù)原來在同一套實例上的,現(xiàn)在需要拆分遷移到不同的實例上,這個我們也陸陸續(xù)續(xù)遷移50+的DB,現(xiàn)在還在有些在遷移。 下一個改造是我們現(xiàn)在用DRC做跨機房的數(shù)據(jù)同步了,所有的數(shù)據(jù)同步都是原生的改成DRC的模式,也會做很多的調(diào)整。 還有一個問題,就是賬號網(wǎng)段也需要做調(diào)整,因為我們原來基于安全考慮會限制某些IP網(wǎng)段,現(xiàn)在網(wǎng)段范圍放大了,所有賬號都要面臨調(diào)整網(wǎng)段的問題,如果量比較多的話,調(diào)整賬號風(fēng)險還是挺高的(很多歷史遺漏會使得主從賬號不一致,同名賬號不同網(wǎng)段等問題,如果出現(xiàn)不一致調(diào)整的時候主從會中斷)。 另外怎么保證全局參數(shù)的一致性,起碼要保證同一個集群,在各個機房參數(shù)都是一致的,這個是比較臟活累活的東西,但是很容易出問題,到處是坑。 另外HA也面臨改造,因為原來在一個機房,現(xiàn)在有多個機房,怎么做到HA的可靠性也是一個問題。這塊我們也做了很多的改造。 改造完成之后,我們對比下改造前后在數(shù)據(jù)庫這端的變化。實例就翻了一倍,集群數(shù)量、Proxy配置、數(shù)據(jù)量、HA都會翻倍。這里特別列了一些DDL的變化,為什么會有變化,因為DRC不做DDL同步這個事情,這個事情都需要DBA分開機房來做(后面會細(xì)講)。 機器故障每周也增加了,原來一周碰不到一臺,現(xiàn)在可能一周面臨兩到三臺這樣的機器故故障,所以必須要保證你的HA是足夠可靠的。 但是我們?nèi)藬?shù)是沒怎么增加,而且我們馬上要上第三個zone,維護(hù)的工作量會增加更多,不過我們沒有加人的計劃,之所以這樣是因為我們在把很多的工作通過平臺、自動化和項目的方式來推動解決掉。 四、DBA挑戰(zhàn)剛剛講了那么多的改造前后的變化。對DBA來講,除了業(yè)務(wù)在多活的時候做改造,架構(gòu)在多活時候的支持外,我覺得做多活改動最大的就是DBA了,對DBA的挑戰(zhàn)真的很大。就像前面說的在集群數(shù)量很大的情況下,怎么有效保障數(shù)據(jù)一致性、HA、配置、容量,還有DDL等問題。 我們可以看一下。剛剛講數(shù)據(jù)這塊我們需要保證他不能錯、不能亂,也不能說因為有一些數(shù)據(jù)的沖突,我們整個的數(shù)據(jù)流就停下來,這也不合理,否則多活就沒有意義了。 再一個即便是把前面流量的東西,都按規(guī)則走了,但你也不能保證各個組件不會出一些bug的問題,比如說DRC同步的時候就有bug,我們就要有兜底的檢測,把有問題的數(shù)據(jù)及時的發(fā)現(xiàn),甚至是修復(fù)好。 所以我們DBA研發(fā)了一個DCP的平臺,DCP就是為數(shù)據(jù)一致性兜底的,它會全量的對比我們各個機房的數(shù)據(jù),告訴DBA到底什么時候有數(shù)據(jù)不一致的問題,大概是多少,是什么樣的類型,怎么修復(fù),不一致量大的時候還需要有合適的修復(fù)工具。 對DCP設(shè)計來說,因為我們有很多套集群,變動很多,如果說一旦變動就要人為調(diào)整的話,這個維護(hù)量也是很大的,也很難保證它的準(zhǔn)確無誤,所以它必須能自適配。它需要支持全量、增量、延時的控制校驗和隨時手動校驗。 延時校驗就是我們有時候跨機房的時候天然就面臨延時,這時候如果有延時數(shù)據(jù)肯定有差異,DCP需要知道到底是因為延時導(dǎo)致的數(shù)據(jù)不一致還是數(shù)據(jù)真的不一致。 還有黑白名單機制,自定義規(guī)則,白名單有一些表我們不需要校驗就可以跳過。自定義規(guī)則就是可以設(shè)定一些相應(yīng)的過濾條件來比較,濾掉一些不需要比較的數(shù)據(jù)。 DCP不光是支持對數(shù)據(jù)一致性的校驗,表結(jié)構(gòu)不一致了也需要校驗,甚至說多維數(shù)據(jù)也能提供校驗支持,比如說一個訂單可能根據(jù)用戶做了拆分,也根據(jù)商戶做了拆分,這兩個數(shù)據(jù)是否一致是需要校驗的。還有我們需要控制比較的時候它的延時、并發(fā)、校驗的時長等,因為你的校驗一直在跑,消耗過大,跑的時間很長勢必對生產(chǎn)會造成影響。 最后我們是需要提供靈活修復(fù)的工具和配套的腳本。這樣比出來的數(shù)據(jù)才能夠快速的恢復(fù),否則你雖然知道數(shù)據(jù)有問題,但要找這些數(shù)據(jù)怎么樣不一致的,怎么去修復(fù),再根據(jù)條件去把腳本寫出來,這個過程就很長了,等你修復(fù)說不定業(yè)務(wù)已經(jīng)影響比較大了。 DCP平臺上線以后,每天大概有400多套集群需要校驗,日均校驗的數(shù)據(jù)有60多億,分鐘級別的校驗頻率。實際發(fā)現(xiàn)數(shù)據(jù)一致性的問題起碼有50+例。 不一致的原因可能是業(yè)務(wù)寫錯了,DRC出BUG了,還有可能是各環(huán)節(jié)(包括DB)的配置問題,如果你沒有相應(yīng)數(shù)據(jù)校驗的工具,其實你是很難知道到底數(shù)據(jù)是不是一致的,多活做的時候這個情況必須要能掌握,否則心里沒底了。 剛剛講的是數(shù)據(jù)校驗DCP的平臺,還有一個HA的保障,集群數(shù)量翻番了,這時候你需要保證任何一個節(jié)點掛了都能盡快的切過去,同時如果你的節(jié)點有調(diào)整有下線等,你都需要保證HA配置能夠跟著變動,否則HA的成功率就會得不到保證,800多套集群也不可能再依賴人肉去保證了。 所以我們做一個EMHA,他有什么作用呢?首先集群任何節(jié)點變動都能夠自動感知,當(dāng)然我們底層是依賴于MHA的,MHA的配置大家用過的話都知道它需要對SSH做互通,有任何一個調(diào)整需要把他從配置文件里面加進(jìn)去或者刪除,否則切換就有問題,所以EMHA新增了自動感知配置保持的功能,自動解決這些問題。 第二個重要的功能是變動信息的擴散通知的機制,因為我們是通過DRC同步數(shù)據(jù)的,如果有一個master出問題切換了,這時候要通知DRC去連新的master,并且還需要提供相應(yīng)的位點信息,還有各種監(jiān)控也需要得到通知,要知道這個master掛了以后,新的master是哪一個,否則后面維護(hù)的信息其實都會錯亂; 第三點我們的切換需要讓Proxy這一層自動感知,如果不能自動感知的話,每次切換Proxy都需要維護(hù),這個可能會中斷生產(chǎn)的訪問,而且這個維護(hù)質(zhì)量基本也得不到保證,所以EMHA也會自動完成與Porxy配置層信息的互通。 還有配置的保持也是比較麻煩的事情,我們在代理層的配置,如果節(jié)點變動了也需要變(調(diào)整區(qū)別于切換,切換DAL可以通過EMAH自動感知)。有各種參數(shù),如果說調(diào)整不一樣了,也需要全局的同步的,這些東西都需要有很多自動發(fā)現(xiàn)的手段,包括自動處理的方式。 當(dāng)然我們現(xiàn)在有些也還沒有能完成做到自動化(正在努力中),目前還有些是通過巡檢腳本來發(fā)現(xiàn)的,起碼保證能夠發(fā)現(xiàn)它然后解決掉。 容量這塊,現(xiàn)在是兩個機房,兩個機房的流量并不一定均衡,比如上海機房70%的流量,北京機房30%的流量,但流量會隨時切換,所以必須保證每個機房都能夠承擔(dān)所有流量。 當(dāng)然三個機房的話,不一定百分之百的冗余,但也一定要知道每套集群是不是能承載切換過來的流量,否則切換過來就面臨雪崩的效應(yīng)。所以對各項指標(biāo)我們都要有相應(yīng)的水位監(jiān)控,提前發(fā)現(xiàn)這些問題。 還有一個很大的困難是在DDL這塊,因為DRC里面不方便做DDL這個事情,之前我們也嘗試讓DRC同步DDL操作,比如說我們做DDL的時候,一般是用PT工具來做,這個過程要拷貝整張表的數(shù)據(jù),如果這個表比較大,DDL時兩個機房之間的流量就會面臨很大的沖擊,而且延時會相當(dāng)大,比如說100G的表在一個機房做完要同步到另外一個機房去,這沖擊業(yè)務(wù)影響是不可接受的。 所以DDL需要DBA在每個機房單獨做,我們開發(fā)了一套DDL發(fā)布工具。因為我們有很多數(shù)據(jù)類型,有GlobalZone還有shardingZone我們還有大量Sharding 表。對單個業(yè)務(wù)邏輯表的DDL來說,實際上我們一套集群里面有幾百張表,這個表又分布在多套集群里面,所以實際業(yè)務(wù)一張邏輯表的DDL操作,實際DDL需要做一千張表,同時還有各種不同的業(yè)務(wù)集群類型,我們在發(fā)布工具必須要能自動適配和識別這些情況(這個時候元數(shù)據(jù)維護(hù)相當(dāng)重要了,因為人已經(jīng)識別不了啦,只能依靠工具)。 還有剛剛講DDL的時候大家普遍用PT的工具,我們用的時候也發(fā)現(xiàn)了很多問題,畢竟是它是同步觸發(fā)器的,一旦加上去之后,瞬間TPS很高的話,就把數(shù)據(jù)庫打爆了。 所以我們在這塊也做了大量改造,到現(xiàn)在大部分情況下我們已經(jīng)不用PT了,大家看這個圖上有好幾種工具可以選擇。我們基于開源社區(qū)的gh-ost做了一個二次開發(fā)改造,改造后的工具叫mm-ost,是一個跨機房的DDL工具,不僅解決了DDL的時候threadrunning不可控、主從延時不可控的問題,還解決了跨機房延時的問題,速度比gh-ost要快一倍。 我們是多機房,多機房和你做一個機房的DDL時完全不一樣的,因為你的機器可能有差異或者繁忙程度不一樣,可能這個機房DDL做完了,另外一邊要半小時之后才能做完,尤其是一個業(yè)務(wù)邏輯表的DDL對應(yīng)的是上千張物理表的DDL時,差異性就更大了,這樣造成的跨機房延時業(yè)務(wù)可能沒法接受,所以我們需要的不僅是能保證同機房DDL主從延時的可控,還要保證跨機房的延時的可控。 mm-ost現(xiàn)在就能夠支持到跨機房同步完成DDL的時差控制在3到5秒之內(nèi)。這延時對業(yè)務(wù)來說就沒什么感覺了,而且他可以支持暫停、探測到DDL數(shù)據(jù)延時的時候能夠減慢速度,能根據(jù)機器負(fù)載動態(tài)調(diào)整DDL的速度等,所以現(xiàn)在DDL基本上對業(yè)務(wù)來說是沒有感覺的。 另外,大家可以看我們的發(fā)布平臺做的很復(fù)雜,它底層調(diào)用的是mm-ost,在發(fā)布平臺上我們也做很多控制,比如說DDL空間滿不滿足,各個主機是不是都滿足去做DDL的條件,主從我們需要控制的延時在30秒之內(nèi),有鎖的時候需要減緩速度,還支持定時執(zhí)行(因為我們有些業(yè)務(wù)的低峰是晚上4點,所以DBA不可能每次都是4點來做這個事情,這時就要定時功能的支持)。 另外系統(tǒng)還可以通過識別業(yè)務(wù)高低峰推薦什么時候做DDL比較合適,還有一些風(fēng)險識別的控制,我們還要預(yù)估DDL的時長,如果開發(fā)問一個500G的表DDL大概多久能做完?你需要能大概告訴他,給他一個預(yù)期??傊l(fā)布這塊是我們面臨最大的一個挑戰(zhàn),我們在上面做了很多工作。 我們DDL數(shù)量相當(dāng)多,可以說在多活改造的時候,DBA發(fā)布的量是最多的。多活改造期間我們DDL基本上每周的工單都在四位數(shù),四位數(shù)的工單數(shù)量,放到底層來講,可能一個邏輯表生成一千個DDL,就是最少是5位數(shù)DDL物理表的量了。 如果完全依賴DBA來執(zhí)行,也很難支持了,所以我們加了自動發(fā)布功能,對于風(fēng)險不高的工單是系統(tǒng)自動執(zhí)行的,粗略的比例大概是8:2,絕大部分都是自動發(fā)布了。風(fēng)險性比較高的工單我們才需要人去處理,我們統(tǒng)計了一下半年大概有15000個工單。 五、收益與展望大概的挑戰(zhàn)主要的方面已經(jīng)跟大家分享了。我們最后看一下多活做完以后收益有哪些。 做多活之前,我們也面臨過很多棘手的問題,比方我們之前面臨著整個機房出現(xiàn)問題(核心交換機出問題、網(wǎng)絡(luò)出問題),還有些機房因為在業(yè)務(wù)沒有那么大之前你不可能預(yù)留特別多的機柜,但你現(xiàn)在說我業(yè)務(wù)漲的很快,現(xiàn)在要加一千臺機器、兩千臺機器的時候,發(fā)現(xiàn)你加不了,因為你的IDC不能給你這個支持,他們不可能給你預(yù)留這么多機柜,這個時候你就面臨單機房沒法擴容的麻煩,之前只能考慮遷移到一個更大的機房去,但也是個耗時費力成本高的事情。 我們多活做了之后,首先打破了單機房容量的瓶頸,單機房不能擴容的時候,我們現(xiàn)在可以在另外的機房擴容我的機器,也可以分不同的流量來滿足負(fù)載,就不再受到單個機房容量的限制。 另一個,多活上線到現(xiàn)在我們流量切了有20次左右,有時候是演練,有時候是真實發(fā)生故障,現(xiàn)在其實就不再受到單機房故障的影響,甚至是單地域的影響,假如說上海哪一天全斷電了對我們影響也不大(當(dāng)然只是指技術(shù)層面)。 還有故障兜底,有的問題可能是比較麻煩的問題,一下子沒有辦法判斷或者解決,那時候可能影響很大,但只影響單個機房,這個時候就可以把業(yè)務(wù)切到另外一個機房,等我們把問題解決了以后再把流量切回來,這樣對業(yè)務(wù)就基本沒有損失了,所以多活之后對我們整體可用性也有一個很大提升。 另外一塊是動態(tài)調(diào)整各個機房的流量,尤其是在做一些促銷活動的時候,有些地區(qū)的流量明顯是不均衡的,這時候如果能動態(tài)的調(diào)整機房之間的流量訪問,這是比較好的分擔(dān)壓力,像阿里雙11這種活動,應(yīng)該會根據(jù)流量壓力來調(diào)整各機房之間的分配。 接下來在來講下多活這塊后續(xù)我們可能要做一些事情,一個是剛剛講的多個機房,我們現(xiàn)在正在準(zhǔn)備第三個機房,因為兩個機房的代價比較高,冗余比較多,我們需要做第三個機房分?jǐn)傔@塊的成本,當(dāng)然一開始成本是比較高的,往后業(yè)務(wù)繼續(xù)上漲的話,可能不需要做太多的擴容。而且現(xiàn)有百分之百冗余的機器資源,可以再做調(diào)配,這樣成本往后來看的話是會下降的。 另外一塊是數(shù)據(jù)的Sharding,這個我們還沒有做到,因為我們在各個機房都是全量的數(shù)據(jù),這也是我們后面努力的方向; 還有一個是自動動態(tài)擴縮容,我們需要有更細(xì)的控制能力來自動的完成這些動作,尤其是在硬件資源利用率上能動態(tài)調(diào)整; 最后一個點是希望能夠提供多機房數(shù)據(jù)強一致性的架構(gòu)方案,因為我們現(xiàn)在來講都是最終一致性的,怎么對一些非常重要的數(shù)據(jù),提供各個機房數(shù)據(jù)及時強一致性,這塊也是我們接下來需要努力的方向。 更多相關(guān)文章閱讀 Python 編程中常用的12種基礎(chǔ)知識總結(jié) 青銅到王者,快速提升你 MySQL 數(shù)據(jù)庫的段位! 學(xué)好 Python、拿高薪、竟是如此簡單 快加入高維學(xué)院直通車成為認(rèn)證運維開發(fā)工程師 只需要5天! 在5天內(nèi)集中向你傳授面向 DevOps 的運維開發(fā)工程師所需要掌握的所有精華。 更有含金量的是,學(xué)習(xí)結(jié)束你還將擁有一張【運維開發(fā)工程師認(rèn)證證書】 這份含金量超高的證書: |
|