阿里云智能資深技術專家 閆衛斌

我今天分享的題目是:“如何打造具備極致容災能力的對象存儲”。

容災是分布式存儲領域的一個關鍵問題。

最基礎的是對服務器的容災,這是所有對象存儲產品都要解決的問題。

進一步,就是AZ(Availability Zone)級故障容災,AZ也就是可用區。通常一個可用區會映射到一個或者多個數據中心。一個AZ和其他AZ在制冷、供電等方面都是故障域隔離的。幾大云廠商也都提供支持AZ級容災的對象存儲產品。

可能有的同學會問,做AZ級容災是不是有必要?大家如果去網上去搜索一下就會發現,各大云廠商的AZ級故障還是時有發生的,包括一些不可抗災害或者制冷、供電中斷等故障。從底層邏輯上來講,AZ級故障是不可能徹底避免的。對于一些高可用的應用,采用具備AZ級容災能力的存儲產品還是非常有必要的。

Region故障也是同樣的道理。每個AZ之間會間隔幾十公里,但是在一些極端場景,比如高等級地震的時候,那同時影響到一個Region的多可用區也是有可能的。比如最近土耳其7、8級地震,它是有可能導致Region級故障的。各家廠商也有提供一些應對Region故障的產品或者說解決方案,對象存儲OSS也有類似的產品,后面會介紹。

本次分享。首先會介紹我們在本地冗余,也就是LRS(本地冗余)這個產品做了哪些容災設計,其次,我會介紹我們應對AZ故障的ZRS(同城冗余)產品的容災設計,第三部分是應對Region故障的跨區域復制功能。在第二、第三部分我分別以案例深入介紹我們在技術上做的一些改進或者設計。最后分享我們是如何以智能運維平臺來應對生產過程中系統長時間運行以后架構腐化的問題。

一、LRS(本地冗余產品)的容災設計

這個圖左邊是我們OSS系統模塊的劃分圖,從上到下大致可以分為四層。

用戶請求進來之后,首先會到達我們的負載均衡,也就是AliLB,AliLB是阿里自研的高性能的負載均衡產品,它是基于LVS原理的。

往下請求會來到業務層,在這一層主要是做協議的解析、各種各樣的業務功能的實現。這兩層我們都是一個無狀態的設計。在這種無狀態的服務里面如何做高可用的呢?我們會把它的部署按機架來打散并保證兩個機架故障情況下,它的服務能力還是足夠的。

再往下,請求就會來到索引層,索引層我們叫做KV,是一個Master Server結構。每個Server又根據字典序劃分為多個分區,它的Master跟每個分區的Server都是采用Raft協議實現的一致性組。

底下就是存儲服務盤古,它跟KV類似,也是一個Master Server的結構。區別是它的Server沒有采用一致性組的架構,主要是性能考慮。另外在高可靠上是通過副本或者EC機制來做的。

在LRS產品里,阿里云整體的容災設計目標是希望做到兩個機架故障不影響服務的可用性和可靠性。

剛才已經提到了無狀態服務,對有狀態服務的話,他們的一致性組,我們都是采用五節點部署的。這五個節點會打散部署在至少五個機架上。這樣顯而易見:如果說故障兩個機架,還是有多數節點存活,還可以提供服務。

數據方面,我們有兩種數據的存放形式,有三副本,也有EC。三副本的話,只要做了機架打散,顯然是可以實現兩機架的容災的。對于EC,我們也會保證它的校驗塊的數量大于等于二。同樣也是做機架打散,能實現兩個機架故障不影響可用性可靠性。

除了這些數據的分散方式,我們還做了非常多的其他的設計來保障高可用。比如數據分片是做全機群打散的,這樣做有什么好處呢?如果一臺服務器發生故障,如果做全打散的話,是可以利用這個集群里剩余的所有機器來并行的做數據修復,這樣縮短了數據的重建時間,相應的也就提高了可靠性。

另外,我們也會剛性的保留足夠的復制帶寬。所有的這些,包括集群水位,副本的配置,包括打散方式,還有復制帶寬,我們都會用一個模型來去計算并且測試驗證它的可靠性,保障設計達到12個9的可靠性。

二、ZRS(同城冗余)產品容災設計

通俗來說,OSS ZRS(同城冗余)產品,也叫3AZ型態。它和LRS最主要的區別就是在容災設計目標上,LRS要容忍兩個機架故障,ZRS則是要保證一個AZ外加一個機架故障時不影響可靠性可用性。

稍微提一下,假設你一個AZ故障發生以后,如果修復時間相對比較長,那再壞一臺機器的概率還是比較高的。如果在容災設計上只容忍1AZ的話,最后因為AZ修復期間單臺服務器的故障影響了可用性,那就有點得不償失了,所以我們在設計上特意采用了1AZ加額外一機架的故障容忍的設計目標。

再來講講怎么實現容災設計的。

在模塊劃分上ZRS和LRS基本是一樣的。主要的區別是模塊的打散方式,在LRS里都是跨機架打散,在ZRS里,我們會把它升級到跨AZ打散,所有的模塊都是跨AZ部署的。當然在AZ內還是會做機架級的打散的。

關于有狀態服務。有狀態服務的一致性組在LRS 都采用5節點部署,ZRS產品里面就會變為9節點。9個節點會均勻打散到3個AZ,每個AZ有3個節點。這個設計是可以容忍4個節點故障的。也就是說可以容忍“1AZ+剩下兩個AZ里的某個節點故障”。

在數據的高可靠方面,前面提過我們有3副本的EC。3副本顯而易見,只要做了AZ打散,是可以容忍剛才提到的容災設計目標的。EC是要做比較大的EC配置的重新設計。理論上,3個AZ要容忍1個AZ故障,那數據冗余至少要1.5倍。實際上早期我們采用6+6的EC配置,大家可以理解一個數據集,把它拆分為6個數據塊+6個校驗塊,平均分布到3個AZ,每個AZ有4個塊。這樣一個AZ故障的時候,一個數據集里還剩余8個塊,其實只要有6個就可以恢復數據了。所以,這個時候還可以再容忍2個機架故障,相比于容災設計目標是有一定的超配。

當然,做了這樣的設計之后,看起來是可以容忍“1AZ+額外1機架故障不影響可用性可靠性”,但實際沒這么簡單。

實際的運行過程中還要考慮到非常多的其他因素。比如如何解決跨AZ的超高吞吐的帶寬需求?AZ間的延遲顯然是要比AZ內的延遲高很多,如何通過系統的設計盡量讓這個延遲的增加不影響到用戶?又比如說在1個AZ故障的時候,本來就有1/3的機器不可服務的,如果還要再做數據重建,那又帶來非常大的IO放大。如何保證在AZ故障時候的高質量的服務?是有非常大的挑戰的。

 接下來以剛才提到的最后這個挑戰為例來做一個相對深入的介紹。

下圖左邊是一個示意圖,我們前面提到了,我們早期是用6+6的EC編碼。我們采用的是RS的編碼。在單個AZ故障的時候剩余8個塊提供服務,其中4個數據塊+4個校驗塊。

簡單計算一下,在這種AZ故障的情況下,單臺機器或者單塊磁盤承受的IO壓力,相比在故障前日常情況下大概是什么水平。

發生故障的時候,顯而易見是有2/3的數據是可以直接讀取的,也就是說1份IO沒有放大。另外有1/3是要通過rebuild來做重建的。重建的話,RS編碼至少要讀6塊數據,不考慮額外的校驗也要讀6塊數據才能重建。也就是說有1/3的數據是要讀6塊才能重建。再考慮故障期間只有2/3的機器提供服務。

右上角有一個簡單的算式,可以看到,故障期間每臺機器或者每塊盤承受的IO壓力是日常的4倍。換個角度來解讀一下,如果這個機器的IO能力是100%的話,那要保證在故障以后還是高可用的,日常最多只能用到它IO能力的25%??紤]還要留一定的安全水位,假設打個八折,那可能就只有20%了,這個數據顯而易見是非??鋸埖?,給我們帶來一個很大的挑戰:要么讓ZRS產品相比LRS只能提供低的多的IO能力,要不然就是要承受高的多的成本。

正因為有這樣的挑戰,所以EC的編碼方式,尤其是在同城冗余型態下EC的編碼方式一直是我們持續投入的研究或者改進的方向,我們也做了非常多的工作,提出了自己獨創的AZC的編碼,這個編碼算法本身也有在頂會中發表論文。

這里對它做一個簡單的介紹。

簡單來說,AZC編碼就是把原本1維的EC編碼升級成了2維。水平方向,是一個AZ間的編碼,我們首先會把一些數據塊劃分為多個小組。每個小組內,如果以上圖左側的示意圖為例,每個小組是“2個數據片+1個校驗片”做了一個2+1的RS編碼。用小的EC配比有一個好處,在AZ故障的時候重建代價小,相比前面要讀6份重建,現在只要讀2份就可以了。

當然這種小配比的EC也是有缺點的,代價就是它的容災能力差,可靠性低。因為只要有2個機架故障,丟掉2個分片,它的數據就無法恢復了,這顯然是不可接受的。所以在垂直方向,也就是AZ內,我們又把多個分組內的數據塊結合到一起,額外做了一個垂直方向的編碼。通常,比如說用12個片,額外再加2-3個校驗塊做一個RS編碼,兩者結合起來就能在12個9可靠性的前提下,仍然能保證在AZ故障的時候重建的IO放大是比較小的。

當然AZC也不只是AZ故障重建代價低的好處。通過一些仔細的編碼配比的選擇,它的數據冗余相比前面提到的6+6 EC也是要好非常多的。

前面也提到,我們會在垂直方向做一個AZ內的RS編碼。這也就是說日常情況下,如果AZ內有機器故障,是可以在AZ內本地重建的,可以完全避免跨機房的重建流量。也就是說,AZC編碼其實是在AZ的故障重建代價和數據冗余的成本和日常的跨機房重建流量這三個方面取得了一個比較好的平衡。相比6+6 RS編碼提升是巨大的,根據這個公式簡單算一下,流量放大倍數從4降到了2,換句話說,也就是說IO利用能力提升了整整1倍。

近幾年,從ZRS產品業務情況上的觀察,越來越多的客戶開始重視AZ級容災能力,使用ZRS的比例越來越高。在香港故障以后,很多客戶把他們的數據存儲轉到了ZRS型態上。很多本身已經在用LRS的客戶,也想無縫的升級到ZRS。

針對這些需求,結合前面做的各種技術改進,阿里云推出了兩個大的升級。第一,將以前不支持歸檔型的ZRS 升級到支持歸檔類型。另外在遷移能力上做了非常多的工作,支持LRS無縫遷移到ZRS,已經在線下以工單的方式幫非常多的客戶完成了遷移,產品化的遷移功能也馬上會推出。

前面介紹的是AZ級故障的應對,接下來我介紹一下第三部分。

三、Region故障的應對

Region故障的應對,主要是跨區域復制功能。

上圖左邊是一個簡單的示意圖。

前面提到,我們有服務層OSS Server,也有索引層KV Server。所有的請求在到達KV Server之后,增刪改操作都會有一條redolog,而且這個redolog是可以定序的。所以為了實現跨區域復制,首先我們增加了Scan Service,它的功能就是掃描所有的redolog來生成復制任務,并且是可定序的復制任務。

這里要強調一點——我們的復制任務是異步的,它跟用戶的前臺請求完全解耦,也就是說它出任何問題,是不影響用戶的前臺業務的。在圖里用不同的顏色進行了區分。

有了任務之后,第二個重要的模塊就是圖里面的Sync Service,它的功能就是把每個復制任務去源端讀取數據,通過跨區域復制的專線或者公網把它寫到目的端去。除了完成這個復制任務本身以外,也要做很多其他的功能,比如說各種維度的QoS,還有在目的端寫入的時候,因為用戶自己也有可能直接寫入,所以要做一致性的數據沖突的仲裁等等。

這部分我也挑了一個功能來做一個相對深入的介紹,我選的是RTC功能,顧名思義就是數據復制時間控制。

一句話來表達,開啟了RTC以后,OSS會對跨區域復制的RPO時間做一個SLA承諾。在以前如果不開啟的話是不提供承諾的。大多數情況下是可以秒級完成復制的,另外,對長尾情況也保證P999的對象可以在10分鐘內完成復制。另外,我們還提供了非常多的復制進度的監控,比如復制的帶寬量、數據量,復制的延遲情況,剩余多少沒有完成的復制任務等等。

為了實現這些,我們后臺做了非常多的技術改進。

首先,因為是一個跨區域的復制,所以帶寬資源非常寶貴,在帶寬資源管理上做了多維度的隔離。首先就是租戶間的隔離,任意的用戶不能影響到其他的用戶。另外,其他的業務的跨區域的流量不能影響到這個RTC服務的流量。以及其他類型的多種維度的QoS隔離。

除了隔離以外,在優先級上也做了非常多角度的劃分。最直白的就是開啟了RTC,那在復制帶寬上就有更高的優先級。另外,在同一個客戶的RTC的復制邊內,已經延遲了的這些任務,相比剛生成的任務就有更高的優先級等等。

除了物理資源的管理,在架構上也做了很多改造來提升復制的實時性。

舉一個例子,OSS的對象,一個對象是可以支持數十T大小的。如果在這個對象上傳完成之后才開始復制,那顯然不可能做到秒級復制,所以在開啟了RTC之后,我們會用更多的IO來保證復制的實時性。簡單來說,沒開啟RTC的時候,我們是在一個PART 上傳完成之后觸發一個復制任務,如果開啟了RTC,那就會在每個PART的1MB或者其他大小的分片上傳完之后就會生成一個復制任務。這樣才能有比較好的實時性保證。

另外,也做了多種維度的精細化的監控,包括對RPO破線的報警等等。

正是因為所有的這些改進,我們才有信心對客戶承諾RPO的SLA 的保障。

四、防止良好的容災設計在執行中逐步腐化

前面介紹完了我們對服務器故障、AZ級故障和Region故障容災上的設計,但是實際的運行過程中也不是這么簡單的,就像一個良好的架構設計在執行較長時間之后會有各種各樣的腐化問題,容災設計也是同理。

舉一個簡單的例子,前面講了要有IO壓力控制,不管是20%還是40%,總是要有一個IO水位的控制的。假設線上用戶的業務情況增長短時間突破了容災水位,如果不及時做擴容的話,那其實就已經喪失了容災能力了,這就是一個典型的腐化問題。

又比如說前面講了各種EC、3副本的數據分布,理想的情況它是應該分布均勻的,但如果某個版本的軟件在這些數據分布算法上出了bug,那它有可能導致分布不均勻。

所有這些問題都會導致容災設計失效。

OSS如何應對這些問題呢?我們會做一些常態化的運維演練,再結合監控報警和自動修復功能來解決這些容災腐化問題。

這些功能主要都是通過我們的智能運維平臺提供的,最后一部分會對我們的智能運維平臺做一個介紹。

1.對象存儲OSS智能運維平臺-數據湖倉

運維的基礎是數據,要有豐富的數據,才有做智能運維的基礎。

在OSS這里,我們通過多年積累,沉淀了非常多的數據。上圖左下就是運維平臺收集的數據的示意。比如各種各樣的監控數據,如網絡探針,可以從外部探測,知道某個區域不可用了;比如服務器的角度,有機器的多種維度數據;應用角度,有每個進程,每個模塊的日志等各種數據;系統的角度,有內核的內存、CPU、磁盤、進程等等多種維度的數據。

阿里云本身有非常多的橫向的支撐系統,應該是50多個,他們本身有非常多的數據沉淀,我們的運維平臺也做了打通。在數據處理上的話也是非常有挑戰的。這里以一個最簡單的OSS訪問日志的例子。我們的訪問日志每秒鐘有億級的日志條目,在處理上的壓力是非常大的,處理的性能、成本都是問題。我們做了非常多的工作,比如采集端,會在本地做一些加工處理,例如過濾、聚合之類的來縮減數據量。

在縮減完之后,我們會使用阿里云的各種功能非常強大的產品,比如說SLS、Blink來做數據的實時處理。處理的這些結果會存儲到ODPS或者OSS自身這樣的存儲產品里面供后續使用。

對一些離線的數據、復雜的數據處理,我們會用到基于OSS的數據湖方案來處理。

2.對象存儲OSS智能運維平臺:運維動作自動化

如果把這個智能運維平臺比作一個人,數據就像是人的眼睛。接下來,我要講的運維動作有點像人的手腳,給我們提供運動能力。

在這一塊,我們的理念有點像Linux 平臺的理念。首先研發同學會把各種各樣的原子操作、原子運維動作都做腳本化,有點像Linux里的一個個命令,每個命令只完成一件事情,這些運維動作的原則也是每個腳本只完成一件事情。然后我們的運維平臺赤驥提供的工作流功能,有點像Linux里的管道,類似一個個簡單的命令,用管道組合起來提供一些復雜的功能。運維平臺通過工作流,可以把各種基礎的運維動作組合起來,實現一些復雜的運維動作,比如說集群上線,集群下線。

當然,有些運維動作相對來說是比較復雜的。以數據遷移為例,在架構上,通過把一個對象拆成META元數據和 DATA數據兩部分,右下角就是一個對象的簡單示意,可以看一個 META的KV對結合用戶元數據的KV對加若干個數據KV對,就組成了一個對象。通過這樣的架構設計,就能實現提供幾個基礎的運維動作:

第一,可以把一個Bucket數據打散到多個存儲集群,每個集群的比例還可以按照需要做不同的調節,不一定完全對等。

第二,可以通過遷移部分數據來做一些靈活的容量調度。

有了眼睛和手腳之后,在大腦的指揮下就可以做一些復雜的高級動作了,對運維來說,也就是說可以完成一些復雜的運維任務。

2.對象存儲OSS智能運維平臺:復雜運維任務

以我們怎么應對容災腐化的例子來做一個收尾吧。

前面提到過一個例子,就是當業務壓力增長,讓某個ZRS集群的IO壓力超過了安全水位線,這個時候運維平臺首先會收到報警信息。

收到報警信息之后,我們會提前有一些預設的規則,比如報警持續了超過多長時間,報警里面產生的IO壓力,用戶的IO行為是持續的,而不是一個瞬時的行為。明確了這些信息之后就會做出決策,然后就要做數據的調度來把一部分IO壓力遷移到別的集群,來讓原本這個集群的IO水位恢復到安全水位。這個時候它就要去調度前面說的那些數據遷移的原子能力來做遷移。這個時候問題就來了:因為數據和IO壓力其實不是直接關聯的,關系比較復雜,到底要調度哪些數據、調度多少數據才能遷移走想要的那么多IO壓力呢?這個又用到了數據,就是前面講的我們沉淀了各種各樣的數據,其中就有用戶的每個Bucket的IO行為的用戶畫像。

右邊這張圖就是其中某個維度的示意。一個用戶Bucket,我們會持續跟蹤他讀取的行為。舉一個例子,比如說你上傳了一天內的數據,你到底有多少比例是讀它的,1-3天的有多少比例,3天以上的有多少比例。有了這個比例劃分,再結合一個用戶每天IO行為的總量的變化情況,就可以在后臺計算出來,是調度新寫入的數據效率更高,還是遷移寫入了某個時間以上的的數據效率更高、以及要遷多少。

計算出這個結果之后就開始真正做執行了,通過工作流去把指定的數據搬遷到其他集群之后,原本這個集群的IO壓力就恢復到安全水位,等于說靠智能運維平臺,研發人員可以把各種約束都沉淀為這樣的復雜運維任務來錄入智能運維平臺上,保證在長時間運行下所有容災設計都像預期的那樣去工作。

以上,就是本次分享的主要內容,感謝各位的觀看。



未經允許不得轉載:存儲在線-存儲專業媒體 » 阿里云閆衛斌:打造具備極致容災能力的對象存儲
分享到

謝世誠

相關推薦

精品国产午夜肉伦伦影院,双性老师灌满浓jing上课h,天天做天天爱夜夜爽,攵女乱h边做边走