從零開始搭建MongoDB資料庫服務
8月30號,受邀在DBAplus118期線上分享了《從零開始搭建MongoDB資料庫服務》。以下為分享主要內容。
分享大綱
- 什麼是『資料庫即服務』
- MongoDB
- 如何搭建一個MongoDB『資料庫即服務』
什麼是『資料庫即服務』
首先介紹一下『資料庫即服務』。『資料庫即服務』其實是『Database-as-a-service』的中文翻譯,我們看看它在維基百科中的定義:『資料庫即服務』是這樣一種服務模式,它使得應用開發者不再需要自己安裝和維護資料庫,而是由專門的資料庫服務提供商來做,應用開發者可以根據自己的需要去直接使用資料庫服務,並為使用量支付費用即可。我們知道,現在有很多的as-a-service,比如Infrastructure as a Service(IaaS)、Platform as a Service(Paas)還有Software as a Service(Saas)。他們到底都是什麼呢?有什麼區別?
這張圖應該可以很好的解釋這些X-aaS。最左邊是傳統企業的IT,所有的活都要自己干,從數據中心伺服器到操作系統資料庫再到上層業務系統。IaaS開始就進入雲計算的範疇了,最基礎的是雲伺服器,不需要再關心機房啊硬體拉,直接就可以用。然後再往右客戶需要關注的越來越少,臟活累活都交給服務提供商來干。
那麼『資料庫即服務』的情況是怎麼樣呢?
『資料庫即服務』其實可以認為是PaaS的一種變種,主要關注點在資料庫上,客戶不再需要去自己部署資料庫,而是只需要按需使用由服務提供商提供的資料庫即可,資料庫的維護都交給服務提供商來完成,這樣客戶只需關注應用本身即可。
我們來具體看一下使用『資料庫即服務』和原來有什麼不同,這裡除了列舉傳統全部DIY的方式之外,還對比了一種利用IaaS來自建資料庫的方式,這也是現在比較常見的一種做法。我們看到傳統方式,需要做很多事情,這當中還需要涉及多個團隊來協作,非常不容易。然後看看第二種方式,利用IaaS來自建,這裡以阿里雲的雲伺服器ECS為例,這種方式和剛剛相比,省了不少事,但是仍然是比較麻煩的,也可能還需要涉及跨團隊協作。我們再來看看如果是使用『資料庫即服務』呢?
只需要點下頁面上的部署按鈕,就可以等著用了,已經進化為完全自助服務了。從時間上來看,第一種方式可能需要花費數月,第二種可能需要花費數天,第三種則只需要數小時即可。可見『資料庫即服務』的優勢還是很明顯的。
所以說為什麼要『即服務』,其實是一個進化的趨勢。我們經常說人不能太懶,但是懶這個字用在程序猿身上可能並不是不好的東西,因為懶,促使我們會去自動化。最早我們通過人肉操作,下載軟體,編譯部署,然後配置。有一天我們發現經常需要這麼干很累很浪費時間,就開始寫腳本來完成這些操作,生產力開始提高。等到規模更大的時候,比如要同時管理數十台數百台機器,這時候可能分髮腳本也嫌麻煩了,開始寫一些自動化的工具來做這個事情。到最高級階段,就是完全實現自助服務,這是懶的最高境界。
MongoDB簡介
說完了『即服務』以及其重要性,接下來我們看一下今天的另一個主角:MongoDB,因為有些同學可能對這個不了解,所以還是簡單介紹一下。
首先,MongoDB是什麼呢,它是一個Document Store,文檔型資料庫,也是我們經常說的NoSQL。根據DB-Engines的資料庫排名,MongoDB長期霸佔著NoSQL老大的地位,現在是資料庫界一位重量級選手。
事實上,MongoDB可以稱為是一種NewSQL,它融合了傳統關係型資料庫和NoSQL的一些優點。最左邊的3個能力是來自於關係型資料庫。首先,它具備豐富的查詢語句和二級索引。通過這點,用戶可以以足夠複雜的方式來訪問和組織數據。第二點,強一致性。MongoDB支持一個靈活的一致性模型。你可以選擇使用強一致性,或最終一致性,取決於你的業務場景。
第三點,MongoDB能很好的集成到多企業現有技術架構中。右邊3個能力 來自NoSQL,首先是靈活的數據模型,MongoDB的文檔模型允許動態修改schema,不用擔心有任何的性能影響。其次是高性能和高可擴展性,MongoDB可以輕鬆進行水平擴展,從而帶來更高的吞吐和更低的延遲。最後,是全球部署,也就是高可用。接下來我們就來具體講下MongoDB的幾個關鍵特性。
MongoDB的關鍵特性主要是3個,第一個就是靈活動態的文檔模型,第二個是高可用副本集,第三個是MongoDB的水平擴展,也就是sharding。
MongoDB以一種叫做BSON(二進位JSON)的存儲形式將數據作為文檔存儲。具有相似結構的文檔通常被組織成集合。可以把集合看成類似於關係資料庫中的的表:文檔對應的是行,欄位對應的是列。
MongoDB將一條記錄的所有數據聚合在一個文檔中,而在關係資料庫中則傾向於將數據分布在多個表中。這樣做有幾個好處,一是由於數據聚集,減少了多表JOIN的需求,這樣只需要讀一次就可以讀到所有數據,在性能上會有很大優勢。
另外,這種模型更加接近我們平時編程語言中的對象結構,可以方便開發者進行數據映射。
最後就是這種模型是schema-less的,也就是在MongoDB中不需要像關係資料庫一樣去事先定義每個表的schema。
MongoDB一個集合內的文檔之間可以擁有不同的結構,可以輕鬆為一個新的文檔添加和減少欄位,不會有任何的性能影響。這個特性非常適合開發一些新產品,可以快速迭代。
當然,過於靈活就可能導致混亂。有時候我們想要求文檔必須要有某些欄位,某些欄位必須要有固定的類型。為此,MongoDB提供了一個文檔驗證功能來對文檔的格式進行約束。
接下來說MongoDB的第二個關鍵特性,高可用副本集(也可以翻譯成複製集)。
Mongodb副本集由一組Mongod實例(進程)組成,包含一個Primary節點和多個Secondary節點,Mongodb Driver(客戶端)的所有數據都寫入Primary,Secondary從Primary同步寫入的數據,以保持副本集內所有成員存儲相同的數據集,提供數據的高可用。
上圖是一個典型的Mongdb副本集,包含一個Primary節點和2個Secondary節點。
副本集通過replSetInitiate命令(或mongo shell的rs.initiate())進行初始化,初始化後各個成員間開始發送心跳消息,並發起Primary選舉操作,獲得『大多數』成員投票支持的節點,會成為Primary,其餘節點成為Secondary。
這裡『大多數』的定義是副本集內可投票成員的一半以上,當副本集內存活成員數量不足大多數時,整個副本集將無法選舉出Primary,此時副本集將無法提供寫服務,處於只讀狀態。通常建議將副本集成員數量設置為奇數,因為偶數個節點能容忍的節點失效和比他少1個節點的奇數個節點是一樣的,但是可以節省一個節點的數據存儲成本。
除了初始化的時候會進行選舉,MongoDB副本集的高可用服務體現在,當副本集中沒有Primary節點時,選舉都會進行。比如當Primary節點宕機時,剩下的Secondary節點中會選舉出新的Primary(只需要滿足大多數成員存活的條件)。選舉使用的演算法是基於Raft協議,但是可以通過為節點配置選舉優先順序對選舉結果進行控制。
此外需要提一下,有一些比較常見的特殊的Secondary。一個是Hidden,Hidden節點和普通的Secondary的區別是它是對Driver隱藏的節點,也就是客戶端無法訪問到Hidden,另外就是它的選舉優先順序是0,也就是它不能被選舉為Primary。
Hidden節點上擁有數據,因此通常會用來作一些運維任務,如數據備份、計算分析等。
另外還有一個是Arbiter,Arbiter是只參與投票,但是不存儲數據的節點,這可以用在對可用性有要求,又要嚴格控制成本的場景。
此外還有如Priority0節點、Delayed節點等。
MongoDB提供了一種水平擴展的方式,叫做sharding,通過這種方式對資料庫進行擴容,對應用是透明的。通過sharding,可以將一個集合的數據散到多個shard節點上。這裡每個shard都可以是一組副本集。應用程序通過一個路由節點(mongos)來訪問sharding集群的數據。有了sharding,mongodb就可以突破單機的限制,比如磁碟、內存和IOPS等,從而提供更強大的服務能力。
Sharded cluster由Shard、Mongos和Config server 3個組件構成。Mongos本身並不持久化數據,Sharded cluster所有的元數據都會存儲到Config Server,而用戶的數據則會分散存儲到各個shard。Mongos啟動後,會從config server載入元數據,開始提供服務,將用戶的請求正確路由到對應的Shard。
Sharded cluster支持將單個集合的數據分散存儲在多個shard上,用戶可以指定根據集合內文檔的某個欄位即shard key來分布數據,目前主要支持2種數據分布的策略,範圍分片(Range based sharding)或hash分片(Hash based sharding)。
範圍分片下,文檔是根據其shard key的值進行分片。shard key的值相鄰近的文檔比較有可能會被放在同一個shard上,這種方式適用於需要使用範圍查詢的業務。
哈希分片下,文檔根據其shard key的hash值進行分片。這會保證數據分布比較均勻,但是不利於範圍查詢。
隨著數據量的增多,MongoDB也會自動在後台對數據以chunk為單位進行負載均衡。
如何搭建一個MongoDB『資料庫即服務』
接下來介紹一下今天的重點內容,如何搭建一個MongoDB資料庫即服務。
首先,在我看來,資料庫即服務,應該具備這些特性:自動化、按需服務、彈性、安全、高可用和可量化。第一個,自動化,這是非常關鍵的,是實現自助服務的基礎,所有可以被自動化操作的流程都應該被自動化,不需要人工干預。第二個,按需服務,資料庫即服務應該是由用戶驅動的,後台應該要有一個工作流的機制來對需求進行響應。第三個,彈性,可以按需動態擴縮容。第四個,安全,這是毋庸置疑的。第五個,高可用,宕機自動切換。第六個,可量化,服務的使用量可以被衡量、報告並且是可控的。
此圖為資料庫即服務應具備的功能大圖。主要包括生命周期管理、容災體系、監控報警、數據管理和增值服務。生命周期管理包括資料庫實例的新建、釋放、擴縮容等,這是資料庫即服務最基礎的功能。容災體系包括高可用、備份恢復,甚至更高級的如異地容災/多活等等。監控報警一方面就是服務使用量的監控,另一方面則是報警,包括服務不可用的報警,以及一些監控數據異常的報警。數據管理指的就是可以方便的對數據進行管理,如可以提供一些圖形化界面等。增值服務包括審計、診斷服務等。其中審計是資料庫的一個非常重要的功能,一方面可以幫助查證問題,另一方面可以為一些數據分析或診斷提供數據源。診斷服務一方面跟蹤服務的資源使用量,為是否需要擴縮容提供決策依據,另一方面主要為慢查詢提供優化建議。
資料庫即服務的核心架構就是工作流引擎,這是實現自動化及按需服務的基礎。
生命周期管理功能包括資料庫實例的新建、釋放、擴縮容以及遷移。新建一個資料庫實例包括分配資源(主要是主機資源)、安裝資料庫、初始化配置。對MongoDB來說,副本集涉及多個節點,涉及到資源的分配策略,Sharding更多。另外副本集還需要一些初始化工作,sharding需要有一個各組件的組合。釋放實例比較簡單,主要是資源的回收。擴縮容可以分為本地和跨機的擴縮容,其實跨機的擴縮容就是遷移。對於MongoDB來說,遷移可以直接利用MongoDB的添加節點自動同步的特性,還是比較方便的。
生命周期管理功能主要涉及這幾個組件,包括資源管理、規格及配置管理、軟體棧管理和負載均衡。資源管理主要是指主機資源的管理,這裡主機可以是物理機,也可以是虛擬機,如雲主機等。資源管理主要負責資源的分配和回收,此外還包括如何實施資源隔離。規格及配置管理一個是需要為資料庫實例制定一些規格,以方便擴容和縮容,另一方面是負責資料庫相關配置的維護。軟體棧管理則包括資料庫軟體以及其依賴的軟體的安裝維護等,包括操作系統。除了這些,還需要一個負載均衡組件來保證資料庫實例在資源上的分布的均衡,當有主機資源需要下線的時候,能夠做到自動對其上的資料庫實例進行遷移。
對於MongoDB來說,在實施資源分配策略時需要注意的一點是需要保證不要破壞副本集原本的高可用特性。雖然MongoDB副本集自帶了高可用,但是如果你把副本集的所有節點都分布在一台物理機上,那如果這個物理機掛了,整個副本集都沒用了。所以一個起碼的原則是要保證MongoDB多副本的主機安全性,儘可能夠做到機架安全。
現在我們的MongoDB資料庫即服務的架構可以稍微擴充一下了,多了資源服務、規格及配置服務、軟體棧服務以及負載均衡服務這幾個組件。
接下來看一下容災體系,這包括高可用、備份/恢復、異地容災/多活。高可用需要有一個負責健康檢查的巡檢服務,另外還需要有一個容災切換的組件。備份/恢復也是容災體系非常重要的一環,這裡有一個很容易被忽視的事情是需要做備份的有效性驗證。如果備份不是有效的,那等於沒有備份。異地容災/多活是比較高級的容災能力,實施起來比較複雜,有興趣的同學可以參考我之前做過的一個分享 MongoDB異地容災多活實踐
MongoDB副本集自帶了高可用,我們還需要做什麼工作呢?主要是需要保證容災切換的一個可控。以一個經典的3節點P/S/H副本集為例,一方面我們可以通過配置選舉優先順序的方式來保持Primary和Secondary的角色穩定性。另一方面,我們希望在任意時刻,用戶都可以有兩個節點是可訪問的,因此我們需要對節點宕機後的副本集做一些reconfig操作,保證宕機節點最終都會變成Hidden,然後統一對Hidden進行處理,比如重搭等。
容災體系第二個比較重要的點就是備份恢復。備份主要需要做的是需要提供自動/手動的備份方式以及支持一些靈活的備份策略制定,如備份周期/備份保留時間等。恢復主要是看對恢復的形態做成什麼樣,是覆蓋原來的實例還是克隆出一個新的實例來,還有就是恢復的粒度,這取決於備份能力,是只能恢復到某個全量備份,還是可以恢復到任意時間點。關於備份存儲,我們要求的最要 能力是高可靠性。另外就是剛剛提過的備份有效性驗證,不能等到火燒眉毛了才發現備份不可用,需要防範於未然。
關於MongoDB的備份方法,相關的文檔和分享已經有很多了,這裡再簡單提一下。全量備份從實施方式上可以分為兩種,邏輯備份和物理備份。其中邏輯備份主要使用官方提供的mongodump/mongorestore工具。物理備份則可以在文件系統或是更底層的邏輯卷、塊設備這層去做。
從各個指標上對比邏輯備份和物理備份,在備份和恢復效率上,物理備份的優勢比較明顯,不過邏輯備份在兼容性上會比較好。
MongoDB的增量備份主要通過持續的抓取oplog來實現。有了全量備份加增量備份,就可以實現恢復到任意時間點。
至此,我們的MongoDB資料庫即服務的架構又可以得到一個比較大的擴充,主要增加了高可用以及備份相關的一些服務。
接下來看下資料庫的監控報警,性能監控主要涉及性能數據的採集、存儲和展示。採集粒度越細越好,最好能做到秒級。報警則可以分為可用性的報警和性能數據的報警。
具備監控報警能力後的架構圖已經有點滿了,這裡報警服務可以通過巡檢服務和性能數據存儲收集相關數據。
來看最後一個增值服務,一個是審計,主要涉及審計日誌的採集、存儲和分析。另一個是診斷服務,一個是資源使用量上的診斷,另外一個是慢查詢的診斷,可以做一些索引推薦等。
這就是我們的MongoDB資料庫即服務的完整架構,可以看到組件還是比較多的,做一個資料庫即服務還不是那麼容易哈。
最後做一下總結,我認為資料庫即服務的核心特性有兩點,一個是資源池化,另外一個是服務可量化。資源池化後才可以進行資源的自動管理,而我們需要的服務是要能夠被量化的,並且是可控的。現在回顧一下之前的一鍵安裝資料庫,其實背後有許多工作要做。這裡順便做下廣告,如果覺得自己搭建一個資料庫即服務太麻煩,可以考慮使用現成的雲服務,比如阿里雲MongoDB資料庫服務:)你想要的全都有!
作者
明儼,阿里雲資料庫組技術專家,主要關注分散式存儲、Nosql資料庫等技術領域。
原文鏈接:從零開始搭建MongoDB資料庫服務-博客-雲棲社區-阿里雲
更多技術乾貨敬請關注云棲社區知乎機構號:阿里云云棲社區 - 知乎
推薦閱讀:
※雲資料庫高可用解決方案技術解析
※mysql都有可視化了,為什麼還要用控制台…?
※資料庫如何做到多個任意欄位的檢索?(nosql方向)
※關於分散式資料庫和UDDB, 你需要知道的一些事(下)
※關係代數的基本運算