“
運維自動化來源于工作中的痛點,京東數據庫團隊面對的是商城成千上萬的研發工程師,這種壓力推動我們不斷變革。
圖片來自包圖網
然而變革不是一蹴而就,也經歷過從手工到腳本化、自動化、平臺化、智能化的艱難轉變。
所以說是需求在驅動運維體系的建設,而運維自動化的真諦在于解放運維人員,促進人率提升,減少人為故障,要學會培養自己“懶”這個好習慣。
京東的自動化運維體系建設始于 2012 年,下面從三個方面進行介紹:
京東數據庫智能運維平臺
京東業務每年都在以爆發的形式在增長,數據庫服務器的數量眾多,產品線也多達上千條,要支持如此龐大的業務體系,需要一套完善的運維自動化管理平臺。
目前京東 MySQL 數據庫管理平臺簡稱 DBS,主要涵蓋以下內容:完善的資產管理系統、數據庫流程管理系統、數據庫監控系統、數據庫故障管理系統、數據庫報表系統、彈性數據庫系統以及數據庫輔助運維工具等。
涉及到了 DBA 運維的方方面面,實現了 DBA 對 MySQL 的自動化、自助化、可視化、智能化、服務化管理,避免 DBA 因手工操作失誤帶來的生產事故,保障京東數據庫的安全、穩定、高效運行。
這里著重介紹以下部分核心功能組件:
元數據管理
作為自動化運維的基石,它的準確性直接關系到整個數據庫管理平臺的可靠性。
京東數據庫管理平臺從數據庫業務方、DBA 的運維習慣等方面出發,涵蓋機房、主機、業務、集群、實例、庫、表等多個維度:
自動化部署
面對繁雜的數據庫新增,擴容等運維工作,利用自動安裝部署平臺可以徹底解放 DBA。
目前京東的自動化部署系統包含申請服務器、部署數據庫實例、同步數據、一致性校驗、拆分及切換等操作,整個過程流程化,包含各級業務及 DBA 的操作審批,最終達到全面的 MySQL 服務的自動化和流程化部署,如下圖:
主要功能點包含以下內容:
智能分析與診斷
京東的智能分析與診斷涵蓋 4 部分重要的內容,數據庫監控指標采集、診斷分析、故障自愈、趨勢分析。
監控系統
監控系統為數據庫管理提供了精準的數據依據,能夠讓運維人員對生產服務系統運行情況了如指掌,核心的監控指標包含:OS 負載、MySQL 核心指標、數據庫日志等。
通過分析獲得的監控信息,判斷被監控數據庫的運行狀態,對可能出現的問題進行預測,并給出優化方案,保證整個系統穩定、高效。
京東的分布式監控系統采用被動模式,Server 端和 Proxy 端均做高可用,防止單點故障。
以下是整體架構和流程圖:
監控性能分析
數據庫性能智能分析,主要是對數據庫監控數據的二次分析,排除安全隱患。
在實際的生產中,有些隱患沒有達到設置的報警閾值,處于一個報警的臨界點。
其實這種情況是最危險的,隨時可能爆發,為解決這些隱患,我們通過對監控數據的環比、同比、TOP 指標等方面進行分組匯總分析,提前發現隱患。
慢 SQL 分析:
索引分析:
空間分析及預測:
鎖分析:
故障自愈
故障出現的形態千奇百怪,而最核心的內容依賴于監控的輔助分析,如何提供最為精準的信息,所做內容如下:
智能切換系統
京東數據庫服務器的量級較大,會導致出故障的概率相對提高,同時對系統穩定性的要求也較為苛刻。
因此為確保實現數據庫高可用,保證 7*24 小時的持續服務,我們團隊自主研發了數據庫自動切換平臺,實現了自動和半自動兩種切換方式,實現了按單集群級別、多集群級別、機房級別等多維度的場景切換。
切換過程包含監控的修改、資產信息的修改、備份策略的修改、主從角色的修改等,一鍵化完成,避免人為因素帶來的二次故障。
分布式檢測
作為切換系統的核心組件,分布式檢測功能主要解決系統容災方面的問題。
按照京東數據庫服務器多數據中心部署的特征,獨立的數據中心各部署了一個檢測節點,并通過特殊標識的接口域名區分。
當發生切換操作時,切換系統會根據傳入的故障主機 IP 等信息,隨機選取兩個機房接口執行調用,探活操作如果發現有一個節點主機存活,那么認為主機存活;如果發現兩個節點都探測為宕機,那么認為主機宕機。
Master 故障切換
主庫實例故障,切換系統會首先通過分布式檢測系統檢查實例存活狀態,確認宕機后將根據基礎信息中的實例切換標識,選擇使用自動切換或手動切換,兩種切換方式原理相同。
先在切換系統上創建切換任務,手動切換需要 DBA 執行切換按鈕,切換操作會通過 Insert 方式插入數據以驗證實例運行狀態,避免實例夯住和硬盤只讀的情況。
如果沒有存活的從庫,則放棄本次操作并以郵件和短信的方式通知 DBA。新主庫是按照先本地(先連接數少,后 QPS 負載低),后異地的原則選擇,執行切換成功后將變更相應元數據信息,示例如下:
某一主四從的集群,主庫 10.66.66.66:3366 故障,需要切換,如下:
監控系統檢測到主庫宕機,則自動創建切換任務,進行自動切換或者手動切換,以手動切換為例:
選目標實例,假如例子中的 4 個從都是存活的,那么根據先本地后異地原則,選出 10.66.66.68:3366,10.66.66.69:3366。
然后再去查連接數,在連接數都相同的情況下,則去比較 QPS,選出 QPS 負載低的 10.66.66.69:3366 作為目標實例:
切換完成結果如下圖:
Slave 故障切換
從庫實例故障,將故障實例下的域名變更到該集群下的非故障實例上,選擇目標實例方式與主庫實例選擇規則一致。
切換成功或失敗都會發郵件及短信告知相應的 DBA。故障實例恢復后,DBA 判斷是否需要回切。示例如下:
有一主四從的集群,從庫 10.88.88.89:3366故障,需要切換,如下:
監控系統會自動創建任務,并根據先本地后異地原則,然后再查連接數、QPS,確定目標實例為 10.88.88.88:3366,進行自動切換,DBA 可在切換任務列表查看詳情。
切換成功的任務會顯示回切按鈕,DBA 可以執行回切,并查看回切的具體信息。
主從計劃性切換
主從計劃性切換實現了按單集群,多集群的批量切換。執行批量切換時可以查看子任務切換的具體步驟,切換后會有前后架構的對比,具體示例如下:
批量創建任務,選擇原則根據先本地后異地,先連接數后 QPS,10.66.66.66:3366 選擇目標主庫為:10.88.88.89:3366。
批量執行切換:
切換子任務詳細信息,可查看到每個子任務的切換結果,執行步驟及前后架構:
京東 MySQL 數據庫切換系統各功能模塊都已組件化、服務簡化了DBA的操作流程,縮短了數據庫切換的時間。
數據庫自動化備份恢復
架構設計
京東數據庫備份系統在設計之初,就是為了將 DBA 從繁雜的備份管理工作中解脫出來,實現自動處理,減少人為干預,并提高備份文件的可用性。
關于備份文件可用性問題,以輪詢恢復的策略確保每個集群在一個周期內都被恢復到。
系統架構設計如下圖所示:
架構具備以下幾個特點:
調度觸發多樣化,調度中心支持三種類型的觸發方式:
并發控制:由于調度任務設置具有不均衡性,可能某一時刻需要調度的任務較多,容易引起調度系統出現問題,因此執行任務通過控制并發數來使任務調度執行運行更加平穩。
觸發和執行分層:任務觸發本身是輕量級的,而任務執行一般都比較重,因此對觸發和執行進行了分層設計,來防止因為執行時間過長導致后續觸發出現問題。
維護期間任務不丟失:Linux 的 crontab 在停機維護期間要運行的任務開機后并不會再次執行,而基于 的調度中心則會在啟動后運行指定間隔內尚未執行的任務,減少因維護而錯失任務的執行。
備份策略增刪改查:之前公司的備份系統是需要指定特定的 IP,經常因為服務器維護而導致備份失敗,故在設計之初就將備份策略與高可用結合在一起,備份策略指定域名而不是 IP。
從庫因為故障切換時 DBS 會將此從庫上的域名切換到集群內的其他從庫,相應的備份也跟隨到了此從庫,保證了備份服務器是可用的。
失敗自動重試:備份很可能因為偶然因素而失敗,因此加入了備份重試的功能,會對 6 小時以內的備份失敗任務進行備份重試,最多重試 3 次,來獲得更高的備份成功率。
自動恢復檢測:備份在每一步都要嚴格地驗證,但是也無法絕對保證備份文件可用,因此引入了自動恢復檢測機制,來幫助 DBA 對備份文件進行檢測,及時發現因為各種未考慮到的情況導致備份文件不可用的情況。
并且恢復檢測也是審計的一個硬性要求,自動恢復檢測也將 DBA 從繁重的恢復檢測工作中徹底解脫了出來。
調度設計
整個自動化備份恢復系統主要由調度系統、備份系統、恢復系統、恢復檢測系統、自動修復系統組成。
其中調度系統是整個系統核心,通過調度系統來協調其他系統運行。調度系統可以部署 Standby 來實現高可用,執行器以集群部署來實現高可用和橫向擴容。
備份系統每次備份時都會進行實例健康狀態檢查、備份運行狀態檢查等,防止對無效的數據庫實例進行備份。
恢復系統主要是在需要進行數據恢復、彈性擴容等需要從備份文件恢復成運行的數據庫實例時使用,能夠讓 DBA 通過簡單地操作即可完成數據的恢復。
恢復檢測在調度系統的指揮下自動對備份文件可用性進行檢測,來幫助 DBA 及時發現不可用的備份文件。
備份失敗有些是能夠通過失敗自動重試來解決,但有一部分是重試所不能解決的,需要進行相應修復,因此開發了自動修復系統來自動修復因為環境等問題引起的備份失敗。
這里調度系統是最核心的一個系統,是整個備份恢復系統的大腦,當時考察了幾種實現方式。
例如 Linux 的 crontab、Azkaban 和 Python 的開源框架 ,最終認為 更加靈活小巧,調度方式也更加多樣化,使用 Python 開發后期維護成本更低,因此采用 開發了調度中心。
系統前端
主要分為備份策略管理、備份詳情、備份黑名單管理、恢復詳情四個模塊。
備份策略管理:
備份策略管理的頁面包含了備份狀態分布情況、存儲使用情況以及每個集群的當前備份策略狀態。
如果已經添加了備份策略則可以在這里進行(時間、服務器、備份方式)修改、暫停(繼續)、刪除操作,如果沒有添加備份策略,則可以進行添加。
備份詳情:
備份詳情里面展示了最近備份總數、成功數、成功率、當天備份任務運行狀態、備份任務 24 小時分布曲線圖以及備份詳細記錄。
備份詳細的記錄可以根據集群名、項目名等信息進行查詢,方便 DBA 更好地掌握備份運行狀況。
恢復檢測詳情:
恢復檢測頁面包含最近每天恢復檢測數、恢復檢測成功數、成功率柱狀圖、當天恢復檢測任務運行狀態餅圖和近期恢復檢測完成率,有助于 DBA 對恢復概況有更清晰的了解。
數據庫變革
過去
在 之前,京東的數據庫服務實現了容器化,雖然數據庫服務已經完全通過 Docker 容器實現了數據庫服務的快速交付和自動故障切換等基本功能,在一定程度上提高了數據庫服務的穩定性和效率。
但是數據庫服務的運維和使用方式與傳統方式基本無異,比較典型的問題如下:
資源分配粒度過大
數據庫服務器資源標準固定,粒度過大,為數據庫服務可提供的資源標準過少。
資源浪費嚴重
資源分配的標準由DBA 根據經驗決定,存在很大的主觀性,不能根據業務的實際情況進行準確評估。
而 DBA 在分配資源的時候一般都會考慮在 3 年以內不需要對服務進行遷移或者擴容,而一次分配比較多的資源,存在嚴重資源浪費。
而且由于數據庫資源標準固定,標準過大,導致宿主機中的碎片過大,經常出現一臺宿主機只能創建一個容器,而剩下的資源滿足不了任何資源標準,導致宿主機上資源使用率過低。
資源靜態無調度
數據庫服務一旦提供,所占據的資源就會固定,不能根據數據庫的負載進行在線動態的調度,而一旦數據庫的硬盤使用率過高,需要 DBA 人工介入進行擴容處理,效率低下。
現在
基于以上的問題,單純的數據庫服務容器化已經無法解決,我們需要讓數據庫服務更聰明,讓數據庫的資源能夠動起來,提供資源分期交付的功能,于是 應運而生。
基于負載的彈性調度為京東的數據庫資源賦予了智慧,令其資源真正地流動起來,并已成功服務于多次 618 和 11.11 大促。
針對每個業務應用都有邏輯庫,邏輯庫中定義了針對整個業務所有表的拆分鍵( Key)進行哈希取模運算時模的范圍(),在每個邏輯庫中可以創建多張表,但是每個表中必須定義 Key。
通過該 Key 將表中的數據拆分成多個分片(Shard),每個分片都對應一個 , 表示對 Key 進行哈希取模運算之后得到的值( Index)的一個范圍。
每個 Shard 都由一整套 MySQL 主從架構提供數據庫服務支撐。應用程序只跟 Gate 集群進行交互,由 Gate 根據元數據信息和 SQL 語句完成數據寫入和查詢的自動路由。
中的監控中心會對所有的基礎服務和資源使用狀況進行實時監控,并通過在監控中心注冊的 Hook 程序自動進行動態擴容、故障自愈、分片管理等,而這一系列操作對應用程序來說是完全無感知的。
流式資源持續交付
數據庫以前的服務存在資源浪費的一個主要原因就是資源初始分配粒度太大,一開始就為業務提前預支 3 年甚至 5 年的資源。
而資源池中的資源是有限的,不可能讓所有業務都提前預支資源,從而導致有些業務沒有資源。 采用流式的方式進行資源的持續交付。
每個業務接入初始都只會分配標準的 64G 硬盤,隨著業務的發展和數據量的持續增加,會持續增加硬盤容量直到到達硬盤限制的上限 256G。
通過這種方式,我們極大地拉長了數據庫資源的交付周期,進而可以在三年或者五年的所有資源預算到位之前就首先為所有服務提供數據庫服務,提升了數據庫的業務支撐能力。
基于負載的彈性調度
數據庫服務使用的資源分為兩類:瞬時資源和遞增資源。
瞬時資源是指資源的使用率在短時間之內會出現嚴重波動,這種資源主要包括 CPU 和內存。
遞增資源是指資源的使用率不會在短時間之內出現嚴重的波動,而是會緩慢增加,并且支持遞增,不會出現減少的情況,這種資源主要包括硬盤。 對于不同的資源采取了不同的調度策略。
針對于瞬時資源, 為每個數據庫分配三種標準:
每個容器分配的初始資源為標準的下限值,當數據庫服務出現 CPU 負載過高或者內存不足時,會嘗試申請多于下限的 CPU 或者內存。
但絕對不會超過上限,待負載恢復后釋放多申請的資源,直至恢復至 CPU 和內存的下限為止。
針對遞增資源:磁盤,在業務接入之初,統一分配 64G 的硬盤,每當當前磁盤使用率達到 80%,且沒有達到 256G 上限的時候,則進行垂直升級;若容器當前磁盤達到了 256G 上限則進行在線 。
垂直升級:首先會進行資源 check,看宿主機是否有足夠的剩余硬盤資源進行垂直升級,若 check 通過,則會在宿主機施加全局資源鎖,并對硬盤進行垂直擴容再增加 64G。
若 Check 不通過,則在宿主機上提供一個硬盤大小為:磁盤容量+64G 大小,CPU 和內存與當前容器相同的新容器,并將數據庫服務遷移到新的容器上。垂直升級是瞬間完成的不會影響數據庫服務。
在線 :申請兩個新的 Shard,新 Shard 中的數據庫 的硬盤、CPU 和內存標準與當前 Shard 中的完全一致。
根據當前 Shard 中的數據庫主從關系,對新 Shard 中的所有數據庫重建 MySQL 主從關系,然后啟動 Schema 信息拷貝和過濾復制,最后更新路由規則并將讀寫流量切換到新的 Shard 上,將舊的 Shard 資源下線。
無論是垂直升級還是在線 ,都需要注意一個問題:在保證每個分片的 Master 在主機房的前提下,盡量不要將所有的資源都分配在一個宿主機/機架/機房, 提供了強大的親和/反親和性資源分配能力。
目前 的親和/反親和性策略如下:
每個 都有一個主機房,屬于同一個 Shard 中的數據庫實例(目前一個 Shard 中包含一主二從)的資源分配盡量應該滿足:Master 必須屬于主機房,不能有任意兩個實例屬于同一機架,不能有任意三個實例在同一 IDC。
這種策略可以避免某一機柜掉電而導致主從同時出現故障,也可以避免 IDC 故障從而導致所有數據庫實例均不可用。
由于是盡量滿足,所以當資源池中的資源分布不均時,就有可能在資源分配的時候滿足不了上述的反親和性策略。
因此 有一個常駐后臺進程,不停的輪詢集群中的所有 Shard,判斷 Shard 中的實例分布是否滿足反親和性規則,若不滿足,就會嘗試進行實例重新分布。重新分布時為了不影響線上業務,會優先進行從庫重分布。
基于彈性調度的能力, 實現了如下三個功能:
通過在線服務能力擴容、在線自愈和在線接入三大功能,實現了京東數據庫服務的 Always Online 保證。
不止于調度
彈性和流式的資源交付與調度是 的基石,但是除了這兩個核心功能之外, 還在用戶易用性、兼容性和數據安全性等方面做了很多工作,包括如下幾點。
數據保護:在傳統的直連數據庫的方案下,當 Master 出現網絡不可達時,一般都會選擇新的 Slave 變為 Master,然后將原來 Master 上的域名漂移到新的 Master 上。
但是這種方案在網絡抖動的情況下很容易由于 上的 DNS 緩存,而導致雙 Master,并且出現臟寫的情況。從整體架構圖可以看出, 與用戶之間通過 Gate 連接。
Gate 是一個集群化服務,多個 Gate 服務都映射到一個域名下,Gate 通過 IP 地址直接訪問各個 MySQL 服務,而且 Gate 對各個 MySQL 角色的識別完全依賴于元數據服務:。
當 中某個 MySQL 的 Master 產生網絡不可達時,會選出新的 Master,并更新路由元數據信息,最后才做 Master 切換。
這樣就避免了由于網絡抖動和 DNS 緩存而在成雙主和數據臟寫,從而對數據進行了嚴格的保護。
流式查詢處理: 通過在 Gate 層實現基于優先級的歸并排序提供了快速流式查詢的功能,在進行大批量數據查詢時,能瞬時返回部分查詢結果數據,極大提高客戶體驗。
無感知數據遷移: 通過交叉在 Window 函數中分別執行部分存量數據拷貝和增量數據追加的算法,開發了在線數據遷移和接入工具 。
通過 可以將傳統 MySQL 數據庫中的動態數據遷移到 中。
當 中的數據與源 MySQL 中的數據的 lag 小于 5 秒時,首先會將源 MySQL 停寫,待 lag 變為 0 時將源 MySQL 的域名漂移到 Gate 集群,整個遷移過程用戶 無感知。
兼容 MySQL 協議: 完全兼容 MySQL 協議,支持標準 MySQL 客戶端和官方驅動程序接入,并且支持大部分 ANSI SQL 語法。
路由規則透明: 與用戶之間通過 Gate 集群進行連接,Gate 根據用戶發送的查詢語句形成的語法樹和查詢執行計劃得到查詢中涉及到的所有表。
并根據 中的元數據信息獲得各個表的分片信息,最后結合語句中的 Join 中的關聯條件和 Where 字句中的謂詞信息,將查詢或者寫入路由到正確的分片。整個過程都是 Gate 自動完成的,對用戶完全透明。
自助化服務: 將對數據庫服務的實例化、DDL/DML 執行、分片升級和擴容等功能抽象成為獨立的接口。
并借助于流程引擎提供了流程化的完全自助的用戶接入服務,用戶申請數據庫服務成功后, 會將數據庫訪問口令自動推送到用戶郵箱。
展望
過去已去,未來已來。我們后續會更多的從用戶的角度去思考數據庫能夠產生的價值。
我們相信京東以后的數據庫服務會:
*請認真填寫需求信息,我們會在24小時內與您取得聯系。