網易雲數據庫架構設計實踐


本文來自網易雲社區


網易作為國內領先的互聯網技術公司,擁有眾多的互聯網產品與移動手機客戶端應用,例如大家耳熟能詳的網易博客、雲閱讀、雲音樂、易信等。數據庫作為支撐互聯網產品最核心的后台服務,對產品的重要性不言而喻。隨着產品數量以及應用規模的急劇增長,數據庫管理逐漸成為產品發展的瓶頸:

硬件采購周期長,溝通協調成本高,數據庫部署需求難以得到快速響應;

硬件利用率低,資源難以做到按需使用,彈性擴展;

服務可用性差、數據可靠性難以保證;

運維自動化程度低,人力成本高;

監控報警不夠完善,出現問題難以診斷。

上述問題暴露出當前的數據庫管理模式已經難以滿足快速發展的互聯網世界多變的需求,一個全新的,集中式的,更加智能的數據庫管理模式呼之欲出。

網易雲數據庫(Netease RDS)是由網易數據庫技術團隊基於開源的MySQL打造的關系數據庫雲托管平台,構建於網易私有雲IaaS服務之上,面向網易眾多的互聯網和移動終端產品,旨在解決當前數據庫管理遇到的諸多問題,提供數據庫實例管理、備份管理、在線ScaleUp、高可用、計划任務、監控報警、平台管理員等7大類功能,如圖1所示。


圖1 網易雲數據庫核心功能

一、    架構設計

圖2 網易雲數據庫架構

圖2為網易雲數據庫的總體架構圖,下面將詳細介紹各個模塊扮演的角色和主要功能。

NVS:網易私有雲雲主機服務,作為MySQL實例的載體,提供數據庫所需的CPU、內存和網絡資源。每一個MySQL實例都單獨部署在一個虛擬機中,管理服務器通過NVS提供的API創建、刪除和擴展虛擬機。此外,NVS還提供了安全組功能,能夠控制外部訪問的IP和端口。

NBS:網易私有雲雲硬盤服務,向雲關系數據庫提供遠程塊設備存儲資源。MySQL的數據文件,日志文件等都存在NBS中。NBS支持共享和獨享兩種硬盤類型,SSD和HDD兩種磁盤介質,管理服務器通過API可以創建、刪除和擴展硬盤空間。

NOS:網易私有雲對象存儲服務,向雲數據庫提供文件存儲資源。所有的數據庫備份文件都存儲在NOS中。NOS提供了類似AWS S3的API接口,允許上傳、下載刪除對象。

管理服務器:整個系統的調度控制模塊,負責實例管理、備份管理、計划任務、高可用、在線ScaleUp、平台管理員、計費相關功能。管理服務器對外負責處理所有來自用戶的Http管理操作請求,對內通過調用NVS、NBS、NOS提供的API控制底層的計算、存儲和網絡資源。

為了實現高可用,通常管理服務器部署在三個物理節點上,利用Zookeeper提供的分布式鎖的功能,只有一個對外提供服務。如果該服務器宕機,則系統利用Zookeeper提供的選主的功能選出一個新的節點對外提供服務。


圖 3 管理服務器功能模塊

圖3展示了管理服務器的功能模塊,主要包括3層,第一層API層,負責定義數據庫資源和封裝管理操作,對外提供API接口。第二層管理流程層,負責實現所有的管理操作業務邏輯。第三層,調度控制和外部通信層,主要負責控制和調度所有的管理業務流程,同時封裝對外通信的接口。

管理服務器是整個系統的核心,相當於系統的“大腦”。所有的管理操作都是由管理服務器負責觸發、組織和實施的。在設計管理服務器時,我們主要面臨着兩個問題:第一,通常一個完整的數據庫管理流程包含較多步驟,而這些管理流程經常需要動態的添加和修改,所以系統的擴展性和可維護性非常重要。第二,所有的實例都由管理服務器集中管理,如果出現網絡或者其他硬件、軟件故障,造成實例大面積宕機,就會出現大量實例進行故障恢復的情況,而在故障恢復中實例存在重建的可能,這樣就會對底層雲主機、雲硬盤服務造成“風暴”,嚴重甚至會導致整個系統癱瘓,所以限流尤為關鍵。

為解決上述兩個問題,我們在管理服務器中使用了“工作流”和“隊列”的設計。每一個管理流程都被系統定位為一條工作流,每條工作流都是由多個可重復執行的原子操作組成。工作流上的操作都是由線程池中的不同的線程負責完成的,任務之間的並發控制在定義工作流時指定,然后由工作流調度控制模塊負責執行。所有的工作流都被定義在一個XML文件中,支持動態修改。這樣,動態的添加或者修改管理流程成為一件非常容易的事情。為了達到“限流”的目的,我們設計了一個權重隊列,所有進入隊列的任務在進入隊列時會調用一個外部定義的權重計算函數,計算該任務的重要程度,然后進行排序,最重要的任務位於隊首,優先執行。隊列可以設置任務執行的速度,同時允許禁止任何任務執行。

Agent:管理服務器在虛擬機的內部代理,和MySQL實例一起部署在虛擬機中,負責執行管理服務器對MySQL實例的管理操做,同時還負責收集數據庫層的監控信息。

其他模塊:系統庫,負責存儲數據庫實例、備份的元數據信息,作為管理服務器的持久化組件;監控報警服務:負責整理所有的監控信息,允許用戶設置報警條件,並在系統達到預設值后,進行報警;日志分析系統:收集所有組件的日志信息,按照用戶、實例、節點進行歸類整理,進行跟蹤報警;認證授權:負責雲服務用戶的注冊、登陸、權限認證等功能。

此外,系統還使用了開源組件ZeroMQ和Zookeeper。

ZeroMQ:消息隊列,負責管理服務器和Agent之間的消息通信。ZeroMQ是一種更為輕量級的消息隊列,與傳統的AMQP協議的消息隊列不同,它不需要獨立的消息服務器,只需要引用一個lib庫即可實現節點之間的通信。因為異步傳輸、LockFree、消息不持久化等特性,ZeroMQ相比其他消息隊列具有更高的消息通信效率。ZeroMQ的設計理念是專注於底層消息的通信,所以ZeroMQ不負責消息的持久化和序列化。對於持久化問題,上層應用可以通過消息重發來保證消息的可靠傳輸,但是這需要接收方能夠判別重復消息,這個可以通過版本號的機制解決,即每一個消息都附帶一個版本號字段,重復消息使用相同的版本號,接收方記錄當前的版本號,如果出現等於或者小於當前版本號的消息,則認為是重復消息。對於序列化的問題,可以使用google的開源序列化框架protobuf實現。

Zookeeper:開源的針對分布式系統的可靠協調系統,在雲數據庫中主要實現多個管理服務器之間的分布式鎖、統一配置管理和選主的功能。管理服務器在啟動時,會去Zookeeper上生成一個有序節點,同時如果該節點不是最小節點,則需要watch前一個比它小的節點,只有最小節點的管理服務器對外提供服務。如果該服務器宕機,則watch該服務器對應節點的standby節點被喚醒,成為新的對外服務節點,這樣避免了多個standby 同時watch對外服務節點造成的“驚群現象”。同時,watch宕機節點的所有Agent被喚醒后,會從Zookeeper上獲取新的管理服務器節點的信息,完成了配置修改。

二、    高可用設計

由於雲托管的服務器相比專用的硬件可靠性有顯著下降,所以高可用是雲數據庫首要解決的問題。實現高可用唯一的途徑就是增加冗余,實現自動故障切換。目前現有的業界方案:

DRBD:塊級別的同步復制,不僅管理復雜,且存在嚴重的性能開銷。

共享存儲:在主機宕機后,從機通過掛載到主機的文件系統上,在主機的數據上執行恢復操作。宕機時間取決於存儲引擎的恢復以及預熱的速度,通常難以做到1分鍾內故障恢復。

復制:使用標准的MySQL復制實現主從同步,目前現有的兩種實現:MMM和MHA。MMM不保證數據一致性,MHA需要主機宕機后依然能夠通過ssh獲取到主機的二進制日志。

網易雲數據庫選擇基於MySQL復制實現高可用,面臨的技術難點主要包括數據一致性的保證和實時故障切換:

數據一致性:官方版本的MySQL復制是異步復制,主機上的事務提交以后才會發送給從機,如果在發送給從機前主機宕機,此時主從切換會出現主機上已提交的事務丟失的問題,切換后數據不一致。5.5版本以后MySQL推出了半同步復制,雖然將返回客戶端成功與發送從機同步起來,但是還是沒解決丟數據的問題。為了保證主從數據的一致性,網易MySQL技術組修改了主機事務提交次序,主機上的事務只有得到從機的確認后才會提交,在內部我們稱之為虛擬同步復制(Virtual Sync Replication)。Oracle官方的MySQL 5.7也已經支持類似同樣的功能,相信這會成為今后MySQL數據庫高可用的一種標准手段。此外,為了保證主機寫入性能不受影響,我們在二進制日志層做了GroupCommit減少fsync的次數,提高了二進制的寫入性能。經過測試,虛擬同步復制的性能完全能夠達到甚至超出MySQL原生異步復制的性能水平。需要注意的是,考慮到從機SQL單線程回放效率的問題,我們這里僅僅是將主機上的更新寫入從機的relaylog后即返回,而不是等到從機完全apply該更新(全同步復制),所以從機可能立即讀不到這部分更新,這就需要在主從切換后,需要將從機所有未apply的relaylog全部回放完畢后,再提供給用戶讀寫,這就引入了第二個問題,實時切換。


圖4 復制過程中事務提交流程

實時切換:由於MySQL復制的過程從機是單線程回放主機上的更新,所以往往會出現從機落后的情況。而為了保證數據的一致性,主從切換后從機落后的時間服務是不可用的,所以要實現實時切換,從機使用多SQL線程並行復制是一種有效解決方案。MariaDB提供了基於行的並行復制,要求是Row格式的二進制日志。我們采取了類似MariaDB的實現方式,根據表的主鍵判斷兩個事務是否沖突,從機按照事務分發線程,如果一個事務的更新中包含上一個事務更新涉及的主鍵,必須等待上個事務執行完后才可執行,否則可並發執行。更重要的是,網易MySQL技術組還實現了並行復制的crash safe功能,保證在意外宕機情況下,依然能夠保證主從數據的一致性。

主從切換后,需要對原先的宕機的數據庫實例進行修復操作,首先就是要重啟。但是我們從圖4的事務提交流程可以看出,虛擬同步復制主機事務提交先寫入二進制日志,然后再發送給從機,如果在這個過程中主機宕機,就會出現主機上有一部分未提交的二進制日志,而這部分日志中涉及的事務更新也未在從機執行。對於未提交的二進制日志中的事務,MySQL會在系統啟動時自動提交,這樣就會出現數據不一致的問題。所以我們在重啟前,先對二進制日志進行了修剪,去掉了這部分二進制日志,這樣就保證了啟動后的該實例和當前服務的實例數據一致性,然后再建立到當前對外服務實例的復制關系即可。如果重啟失敗,則系統會將該實例提交給重建隊列進行重建。

三、    系統監控與運維的設計

         除了可靠性,可預測性與控制能力也是雲托管的服務器相比專用硬件的軟肋,所以完善的監控和運維平台是雲數據庫能夠穩定運行的基本保障。

         系統監控,主要采用兩種方式:主動探測和問題跟蹤。所謂主動探測是指由統一的檢測程序定期的調用底層服務和依賴模塊的接口,這種方式能夠提前發現問題,防患於未然,對於網絡、系統庫等調用代價不大的接口非常有效,但是對於創建雲主機、雲硬盤等接口,調用代價過大,並不適用。這時,事后的問題的跟蹤和分析變的異常重要,而日志是最主要的技術手段。對於日志按照輸出級別進行歸類整理,對於錯誤日志,按照錯誤標識進行相應的報警。

從網易雲數據庫的系統架構可以看出,系統作為上層PaaS服務,依賴眾多的底層IaaS服務,同時作為一個分布式系統,擁有管理服務器、Agent、計費、認證等多個模塊,分散的日志首先需要有統一的格式和規范,這個規范必須能夠幫助運維人員快速定位到出現問題的服務和模塊,同時體現服務和模塊之間的調用關系。網易私有雲統一日志格式如下:

ID:用戶請求的唯一標識符,由最上層服務在處理用戶請求時生成,並由上層服務在調用底層服務時傳給底層服務。

Seq:同一請求在同一模塊內的日志寫入序號,格式為“x.x.x”,用戶請求每次跨越模塊,Seq遞加一層(如從“x.x”,擴展到“x.x.x”)。同一模塊內每次寫入日志或者調用其它模塊前對本層級的seq值加1(如“2.1”到“2.2”)。該值隨着服務和模塊之間的相互調用進行傳遞。

Timestamp:打印日志的時間戳。

Level:日志輸出級別,可選值有error、warn、info和debug。模塊內部日志使用debug,模塊之間的調用使用info。

Module:輸入日志的模塊和服務名稱。

Ip:產生日志的服務器IP。

Identifier:用戶的標識符。

Op: 日志執行的操作。

Object:操作對象信息,使用Json格式。

description:日志詳情,須包含全部異常堆棧。

整個日志規范中最為核心的就是ID和Seq字段,ID是連接多個服務和模塊的線索,Seq是體現服務和模塊之間調用層級關系的標識。一次雲數據庫創建請求的ID和Seq變化如圖4所示。

圖 5 統一日志ID和Seq變化

有了統一的日志格式,剩下的就是一個能夠提供日志收集,歸類、分析和展示的運維平台。我們利用公司內部的一個日志收集和分析平台LogTracer來收集各個底層服務和系統內部模塊的日志,然后進行統一的分類、標注和歸檔,最后存儲在Mongodb中,運維人員登陸運維平台,即可方便的根據請求ID,模塊、日志級別等進行檢索,同時能夠展示出清晰的服務和模塊之間的調用關系。


圖6 運維平台統一日志

四、    ScaleUp與ScaleOut    

數據庫的擴展主要分為兩類:ScaleUp和ScaleOut。ScaleUp是指通過增加一台服務器的資源來增強數據庫實例的處理能力。資源的動態伸縮是雲最顯著的優勢,所以在雲環境下ScaleUp將會變得非常容易。但是底層資源的伸縮過程中,會出現服務的中斷,造成數據庫的不可用,所以雲數據庫的ScaleUp需要解決的是資源擴展過程中服務可用性的問題。

借鑒高可用的設計思路,可以通過創建冗余,在從機上先進行ScaleUp,然后通過一次主動的主從切換,將服務切換到已經完成ScaleUp的實例上,從而完成不停服的在線ScaleUp過程。

圖 7 雲數據庫在線ScaleUp

雖然ScaleUp在大多數情況下都能夠滿足產品的需求,但是單台數據庫的性能總是有上限的,尤其是在雲環境下,由於各種資源的限制,導致數據庫會更早的到達性能瓶頸,這時ScaleOut成為用戶的必然選擇。ScaleOut是指通過將用戶請求分布到多個數據庫實例上來提高整體的處理能力。按照網易私有雲的規划,網易雲數據庫並不直接提供用戶sharding的功能,而是作為另外一個私有雲PaaS服務分布式數據庫的底層節點對外提供服務。分布式數據庫服務直接利用雲數據庫提供的API實現數據庫實例的操作和管理,然后在上層實現sharding的功能。

五、    結束語

雲計算擁有低成本、高資源利用率、可擴展等諸多優勢,是企業未來資源管理的發展方向。但是雲計算並不是天生為數據庫設計的,在雲端使用關系數據庫面臨着軟硬件可靠性差、可預測性低和控制能力弱等諸多挑戰,網易雲數據庫在架構設計中充分考慮了上述因素的影響,通過虛擬同步復制實現了完全可靠的高可用,通過提供了統一的日志跟蹤運維平台方便故障排查和分析,同時提供了在線ScaleUp的功能滿足用戶自動擴展的需求。目前,已有較多的網易產品使用雲數據庫。

雖然雲數據庫提供的功能已經能夠滿足大多數網易產品的需求,但是仍有較多改進和發展的空間。例如,當前的我們是基於KVM來實現底層計算資源的虛擬化的,未來我們傾向於LXC(Linux Container)更輕量級的虛擬化技術,在功能方面,我們會提供多版本管理等滿足更多用戶的需求。

 

網易雲新用戶大禮包:https://www.163yun.com/gift

本文來自網易雲社區,經作者郭憶授權發布。

 



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM