團隊介紹
京東商城技術架構部-資料庫技術部,負責為京東商城提供高效穩定的資料庫服務以及資料庫生態商品的研發,主要關注:資料庫AIOps系統、資料庫核心、多模型資料庫系統、彈性資料庫、BinLake、JTransfer以及資料知識圖譜等產品的研發,部門秉承技術至上、不斷創新的理念在資料庫領域不斷前進。
運維自動化來源於工作中的痛點,京東資料庫團隊面對的是商城成千上萬的研發工程師,這種壓力推動我們不斷變革,然而變革不是一蹴而就,也經歷過從手工到指令碼化、自動化、平臺化、智慧化的艱難轉變,所以說是需求在驅動運維體系的建設,而運維自動化的真諦在於解放運維人員,促進人率提升,減少人為故障,要學會培養自己“懶”這個好習慣。
京東的自動化運維體系建設始於2012年,下面從兩個方面進行介紹:
一、京東資料庫智慧運維平臺
京東業務每年都在以爆發的形式在增長,資料庫伺服器的數量眾多,產品線也多達上千條,要支援如此龐大的業務體系,需要一套完善的運維自動化管理平臺。目前京東MySQL資料庫管理平臺簡稱DBS,主要涵蓋以下內容:完善的資產管理系統、資料庫流程管理系統、資料庫監控系統、資料庫故障管理系統、資料庫報表系統、彈性資料庫系統以及資料庫輔助運維工具,涉及DBA運維的方方面面,實現了DBA對MySQL的自動化、自助化、視覺化、智慧化、服務化管理,避免DBA因手工操作失誤帶來的生產事故,保障京東資料庫的安全、穩定、高效執行。
這裡著重介紹以下部分核心功能元件:
作為自動化運維的基石,它的準確性直接關係到整個資料庫管理平臺的可靠性。京東資料庫管理平臺從資料庫業務方、DBA的運維習慣等方面出發,涵蓋機房、主機、業務、叢集、例項、庫、表等多個維度:
機房和主機維度:主要記錄硬體方面的資訊。
業務維度:主要記錄業務的名稱、等級及業務部門相關資訊。
叢集維度:主要記錄MySQL叢集架構資訊。
例項維度:主要記錄MySQL的相關引數,為後續自動化運維提供保障。
庫維度:主要記錄資料庫名稱及業務人員聯絡資訊。
面對繁雜的資料庫新增,擴容等運維工作,利用自動安裝部署平臺可以徹底解放DBA。目前京東的自動化部署系統包含申請伺服器、部署資料庫例項、同步資料、一致性校驗、拆分及切換等操作,整個過程流程化,包含各級業務及DBA的操作審批,最終達到全面的MySQL服務的自動化和流程化部署,如下圖:
主要功能點包含以下內容:
安裝部署MySQL例項,架構搭建,域名申請。分配規則要求同一叢集主從例項不能在同一機櫃,硬體效能好的主機優先為主庫。
監控部署,備份部署,資產註冊。
MySQL服務採用映象的形式建立,映象依賴於K8S的映象倉庫。
應用賬號是應用方透過自動化上線系統申請建立的。
主從資料一致性校驗,通常會選擇夜間業務低峰期定時執行。
京東的智慧分析與診斷涵蓋4部分重要的內容,資料庫監控指標採集、診斷分析、故障自愈、趨勢分析:
(1)監控系統
監控系統為資料庫管理提供了精準的資料依據,能夠讓運維人員對生產服務系統執行情況瞭如指掌,核心的監控指標包含:OS負載、MySQL核心指標、資料庫日誌等。透過分析獲得的監控資訊,判斷被監控資料庫的執行狀態,對可能出現的問題進行預測,並給出最佳化方案,保證整個系統穩定、高效。
京東的分散式監控系統採用被動模式,server端和proxy端均做高可用,防止單點故障。以下是整體架構和流程圖:
(2)監控效能分析
資料庫效能智慧分析,主要是對資料庫監控資料的二次分析,排除安全隱患。在實際的生產中,有些隱患沒有達到設定的報警閾值,處於一個報警的臨界點,其實這種情況是最危險的,隨時可能爆發,為解決這些隱患,我們透過對監控資料的環比、同比、TOP指標等方面進行分組彙總分析,提前發現隱患。
慢SQL分析:
索引分析:
空間分析及預測:
鎖分析:
(3)故障自愈
故障出現的形態千奇百怪,而最核心的內容依賴於監控的輔助分析,如何提供最為精準的資訊,所做內容如下:
告警過濾:將告警中不重要的告警以及重複告警過濾掉
生成派生告警:根據關聯關係生成各類派生告警
告警關聯:同一個時間窗內不同型別派生告警是否存在關聯
權重計算:根據預先設定的各類告警的權重,計算成為根源告警的可能性
生成根源告警:將權重最大的派生告警標記為根源告警
根源告警合併:若多類告警計算出的根源告警相同,則將其合併
京東資料庫伺服器的量級較大,會導致出故障的機率相對提高,同時對系統穩定性的要求也較為苛刻。因此為確保實現資料庫高可用,保證7*24小時的持續服務,我們團隊自主研發了資料庫自動切換平臺,實現了自動和半自動兩種切換方式,實現了按單叢集級別、多叢集級別、機房級別等多維度的場景切換。切換過程包含監控的修改、資產資訊的修改、備份策略的修改、主從角色的修改等,一鍵化完成,避免人為因素帶來的二次故障。
(1)分散式檢測
作為切換系統的核心元件,分散式檢測功能主要解決系統容災方面的問題。按照京東資料庫伺服器多資料中心部署的特徵,獨立的資料中心各部署了一個檢測節點,並透過特殊標識的介面域名區分。當發生切換操作時,切換系統會根據傳入的故障主機IP等資訊,隨機選取兩個機房介面執行呼叫,探活操作如果發現有一個節點主機存活,那麼認為主機存活;如果發現兩個節點都探測為當機,那麼認為主機當機。
(2)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作為目標例項:
切換完成結果:
(3)Slave故障切換
從庫例項故障,將故障例項下的域名變更到該叢集下的非故障例項上,選擇目標例項方式與主庫例項選擇規則一致。切換成功或失敗都會發郵件及簡訊告知相應的DBA。故障例項恢復後,DBA判斷是否需要回切。示例如下:
有一主四從的叢集,從庫 10.88.88.89:3366故障,需要切換,如下:
監控系統會自動建立任務,並根據先本地後異地原則,然後再查連線數、QPS,確定目標例項為10.88.88.88:3366,進行自動切換,DBA可在切換任務列表檢視詳情。
切換成功的任務會顯示回切按鈕,DBA可以執行回切,並檢視回切的具體資訊。
(4)主從計劃性切換
主從計劃性切換實現了按單叢集,多叢集的批次切換。執行批次切換時可以檢視子任務切換的具體步驟,切換後會有前後架構的對比,具體示例如下:
叢集1
批次建立任務,選擇原則根據先本地後異地,先連線數後QPS,10.66.66.66:3366選擇目標主庫為:10.88.88.89:3366。
批次執行切換:
切換子任務詳細資訊,可檢視到每個子任務的切換結果,執行步驟及前後架構:
京東MySQL資料庫切換系統各功能模組都已元件化、服務簡化了DBA的操作流程,縮短了資料庫切換的時間。
(1)架構設計
京東資料庫備份系統在設計之初,就是為了將DBA從繁雜的備份管理工作中解脫出來,實現自動處理,減少人為干預,並提高備份檔案的可用性。關於備份檔案可用性問題,以輪詢恢復的策略確保每個叢集在一個週期內都被恢復到。系統架構設計如下圖所示:
架構具備以下幾個特點:
排程觸發多樣化
排程中心支援三種型別的觸發方式interval、crontab和date:
interval是週期排程,可以指定固定間隔時長的任務排程,支援時間單位有weeks、days、hours、minutes、seconds,並支援設定排程開始時間和結束時間以及時區設定。
crontab是定時排程,與Linux的crontab基本相同,支援year、month、day、week、day_of_week、hour、minute、second,並且支援設定排程開始時間和結束時間以及時區設定。
date是一次性定時排程,支援時區設定。
併發控制
由於排程任務設定具有不均衡性,可能某一時刻需要排程的任務較多,容易引起排程系統出現問題,因此執行任務透過控制併發數來使任務排程執行執行更加平穩。
觸發和執行分層
任務觸發本身是輕量級集的,而任務執行一般都比較重,因此對觸發和執行進行了分層設計,來防止因為執行時間過長導致後續觸發出現問題。
維護期間任務不丟失
Linux的crontab在停機維護期間要執行的任務開機後並不會再次執行,而基於APScheduler的排程中心則會在啟動後執行指定間隔內尚未執行的任務,減少因維護而錯失任務的執行。
備份策略增刪改查
之前公司的備份系統是需要指定特定的IP,經常因為伺服器維護而導致備份失敗,故在設計之初就將備份策略與高可用結合在一起,備份策略指定域名而不是IP。從庫因為故障切換時DBS會將此從庫上的域名切換到叢集內的其他從庫,相應的備份也跟隨到了此從庫,保證了備份伺服器是可用的。
失敗自動重試
備份很可能因為偶然因素而失敗,因此加入了備份重試的功能,會對6小時以內的備份失敗任務進行備份重試,最多重試3次,來獲得更高的備份成功率。
自動恢復檢測
備份在每一步都要嚴格地驗證,但是也無法絕對保證備份檔案可用,因此引入了自動恢復檢測機制,來幫助DBA對備份檔案進行檢測,及時發現因為各種未考慮到的情況導致備份檔案不可用的情況,並且恢復檢測也是審計的一個硬性要求,自動恢復檢測也將DBA從繁重的恢復檢測工作中徹底解脫了出來。
(2)排程設計
整個自動化備份恢復系統主要由排程系統、備份系統、恢復系統、恢復檢測系統、自動修復系統組成。其中排程系統是整個系統核心,透過排程系統來協調其他系統執行。排程系統可以部署Standby來實現高可用,執行器以叢集部署來實現高可用和橫向擴容。
備份系統每次備份時都會進行例項健康狀態檢查、備份執行狀態檢查等,防止對無效的資料庫例項進行備份;恢復系統主要是在需要進行資料恢復、彈性擴容等等需要從備份檔案恢復成執行的資料庫例項時使用,能夠讓DBA透過簡單地操作即可完成資料的恢復;恢復檢測在排程系統的指揮下自動對備份檔案可用性進行檢測,來幫助DBA及時發現不可用的備份檔案;備份失敗有些是能夠透過失敗自動重試來解決,但有一部分是重試所不能解決的,需要進行相應修復,因此開發了自動修復系統來自動修復因為環境等問題引起的備份失敗。
排程系統是最核心的一個系統,是整個備份恢復系統的大腦,當時考察了幾種實現方式,例如Linux的crontab、Azkaban和python的開源框架Apscheduler,最終認為Apscheduler更加靈活小巧,排程方式也更加多樣化,使用Python開發後期維護成本更低,因此採用Apscheduler開發了排程中心。
(3)系統前端
主要分為備份策略管理、備份詳情、備份黑名單管理、恢復詳情四個模組:
備份策略管理:
備份策略管理的頁面包含了備份狀態分佈情況、儲存使用情況以及每個叢集的當前備份策略狀態,如果已經新增了備份策略則可以在這裡進行(時間、伺服器、備份方式)修改、暫停(繼續)、刪除操作,如果沒有新增備份策略,則可以進行新增。
備份詳情:
備份詳情裡面展示了最近備份總數、成功數、成功率、當天備份任務執行狀態、備份任務24小時分佈曲線圖以及備份詳細記錄。備份詳細的記錄可以根據叢集名、專案名等資訊進行查詢,方便DBA更好地掌握備份執行狀況。
恢復檢測詳情:
恢復檢測頁面包含最近每天恢復檢測數、恢復檢測成功數、成功率柱狀圖、當天恢復檢測任務執行狀態餅圖和近期恢復檢測完成率,有助於DBA對恢復概況有更清晰的瞭解。
二、資料庫變革
在ContainerDB之前,京東的資料庫服務實現了容器化,雖然資料庫服務已經完全透過Docker容器實現了資料庫服務的快速交付和自動故障切換等基本功能,在一定程度上提高了資料庫服務的穩定性和效率,但是資料庫服務的運維和使用方式與傳統方式基本無異,比較典型的問題如下:
(1)資源分配粒度過大
資料庫伺服器資源標準固定,粒度過大,為資料庫服務可提供的資源標準過少。
(2)資源浪費嚴重
資源分配的標準有DBA根據經驗決定,存在很大的主觀性,不能根據業務的實際情況進行準確評估,而DBA在分配資源的時候一般都會考慮在3年以內不需要對服務進行遷移或者擴容,而一次分配比較多的資源,存在嚴重資源浪費。而且由於資料庫資源標準固定,標準過大,導致宿主機中的碎片過大,經常出現一臺宿主機只能建立一個容器,而剩下的資源滿足不了任何資源標準,導致宿主機上資源使用率過低。
(3)資源靜態無排程
資料庫服務一旦提供,所佔據的資源就會固定,不能根據資料庫的負載進行線上動態的排程,而一旦資料庫的硬碟使用率過高,需要DBA人工介入進行擴容處理,效率低下。
基於以上的問題,單純的資料庫服務容器化已經無法解決,我們需要讓資料庫服務更聰明,讓資料庫的資源能夠動起來,提供資源分期交付的功能,於是ContainerDB應運而生。ContainerDB基於負載的彈性排程為京東的資料庫資源賦予了智慧,令其資源真正地流動起來,並已成功服務於多次618和11.11大促。
ContainerDB針對每個業務應用都有邏輯庫,邏輯庫中定義了針對整個業務所有表的拆分鍵(Sharding Key)進行雜湊取模運算時模的範圍(KeySpace),在每個邏輯庫中可以建立多張表,但是每個表中必須定義Sharding Key。透過該Sharding Key將表中的資料拆分成多個分片(Shard),每個分片都對應一個KeyRange,KeyRange表示對Sharding Key進行雜湊取模運算之後得到的值(Sharding Index)的一個範圍,每個Shard都由一整套MySQL主從架構提供資料庫服務支撐。應用程式只跟Gate叢集進行互動,由Gate根據後設資料資訊和SQL語句完成資料寫入和查詢的自動路由。ContainerDB中的監控中心會對所有的基礎服務和資源使用狀況進行實時監控,並透過在監控中心註冊的Hook程式自動進行動態擴容、故障自愈、分片管理等,而這一系列操作對應用程式來說是完全無感知的。
(1)流式資源持續交付
資料庫以前的服務存在資源浪費的一個主要原因就是資源初始分配粒度太大,一開始就為業務提前預支3年甚至5年的資源。而資源池中的資源是有限的,不可能讓所有業務都提前預支資源,從而導致有些業務沒有資源。ContainerDB採用流式的方式進行資源的持續交付。每個業務接入初始都只會分配標準的64G硬碟,隨著業務的發展和資料量的持續增加,會持續增加硬碟容量直到到達硬碟限制的上限256G。
透過這種方式,我們極大地拉長了資料庫資源的交付週期,進而可以在三年或者五年的所有資源預算到位之前就首先為所有服務提供資料庫服務,提升了資料庫的業務支撐能力。
(2)基於負載的彈性排程
資料庫服務使用的資源分為兩類:瞬時資源和遞增資源。
瞬時資源是指會資源的使用率在短時間之內會出現嚴重波動,這種資源主要包括CPU和記憶體。
遞增資源是指資源的使用率不會再短時間之內出現嚴重的波動,而是會緩慢增加,並且支援遞增,不會出現減少的情況,這種資源主要包括硬碟。ContainerDB對於不同的資源採取了不同的排程策略。針對於瞬時資源,ContainerDB為每個資料庫分配三種標準:
下限:2C/4G,上限:4C/8G
下限:4C/8G,上限:8C/16G
下限:8C/16G,上限:16C/32G
每個容器分配的初始資源為標準的下限值,當資料庫服務出現CPU負載過高或者記憶體不足時,會嘗試申請多於下限的CPU或者記憶體,但絕對不會超過上限,待負載恢復後釋放多申請的資源,直至恢復至CPU和記憶體的下限為止。
針對遞增資源:磁碟,在業務接入之初,統一分配64G的硬碟,每當當前磁碟使用率達到80%,且沒有達到256G上限的時候,則進行垂直升級;若容器當前磁碟達到了256G上限則進行線上Resharding。
垂直升級:首先會進行資源check,看宿主機是否有足夠的剩餘硬碟資源進行垂直升級,若check透過,則會在宿主機施加全域性資源鎖,並對硬碟進行垂直擴容再增加64G。若check不透過,則在宿主機上提供一個硬碟大小為:磁碟容量+64G大小,CPU和記憶體與當前容器相同的新容器,並將資料庫服務遷移到新的容器上。垂直升級是瞬間完成的不會影響資料庫服務。
線上Resharding:申請兩個新的Shard,新Shard中的資料庫Container的硬碟、CPU和記憶體標準與當前Shard中的完全一致,根據當前Shard中的資料庫主從關係,對新Shard中的所有資料庫重建MySQL主從關係,然後啟動Schema資訊複製和過濾複製,最後更新路由規則並將讀寫流量切換到新的Shard上,將舊的Shard資源下線。
無論是垂直升級還是線上Resharding,都需要注意一個問題:在保證每個分片的Master在主機房的前提下,儘量不要將所有的資源都分配在一個宿主機/機架/機房,ContainerDB提供了強大的親和/反親和性資源分配能力。目前ContainerDB的親和/反親和性策略如下:
每個KeySpace都有一個主機房,屬於同一個Shard中的資料庫例項(目前一個shard中包含1主2從)的資源分配儘量應該滿足:Master必須屬於主機房,不能有任意兩個例項屬於同一機架,不能有任意三個例項在同一IDC,這種策略可以避免某一機櫃掉電而導致主從同時出現故障,也可以避免IDC故障從而導致所有資料庫例項均不可用。
由於是儘量滿足,所以當資源池中的資源分佈不均時,就有可能在資源分配的時候滿足不了上述的反親和性策略。因此ContainerDB有一個常駐後臺程式,不停的輪詢叢集中的所有Shard,判斷Shard中的例項分佈是否滿足反親和性規則,若不滿足,就會嘗試進行例項重新分佈。重新分佈時為了不影響線上業務,會優先進行從庫重分佈。
基於彈性排程的能力ContainerDB實現瞭如下三個功能:
線上擴容:當某個Shard的資料庫負載達到閾值後,會自動觸發Shard的線上垂直升級、遷移或者Resharding。
線上自愈:當Shard中的某個MySQL例項出現故障,ContainerDB首先判斷出現故障的例項是否為master,若是master,則選擇GTID最大的slave作為新的主,並進行復制關係重建和Slave補齊;若不是master,則直接進行slave補齊。
線上接入:ContainerDB允許使用者以完全自助化的方式啟動資料線上遷移與接入任務,該任務會將傳統MySQL資料庫中的資料線上遷移到ContainerDB中,待資料遷移完畢後,自動進行域名切換,完成業務系統資料來源的線上無感知遷移。
ContainerDB透過線上服務能力擴容、線上自愈和線上接入三大功能,實現了京東資料庫服務的Always Online保證。
(3)不止於排程
彈性和流式的資源交付與排程是ContainerDB的基石,但是除了這兩個核心功能之外,ContainerDB還在使用者易用性、相容性和資料安全性等方面做了很多工作,包括:
資料保護
在傳統的直連資料庫的方案下,當Master出現網路不可達時,一般都會選擇新的Slave變為Master,然後將原來Master上的域名漂移到新的Master上。但是這種方案在網路抖動的情況下很容易由於AppServer上的DNS快取,而導致雙Master,並且出現髒寫的情況。從整體架構圖可以看出,ContainerDB與使用者之間透過Gate連線。Gate是一個叢集化服務,多個Gate服務都對映到一個域名下,Gate透過IP地址直接訪問各個MySQL服務,而且Gate對各個MySQL角色的識別完全依賴於後設資料服務:Topology。當ContainerDB中某個MySQL的Master產生網路不可達時,會選出新的Master,並更新路由後設資料資訊,最後才做Master切換,這樣就避免了由於網路抖動和DNS快取而在成雙主和資料髒寫,從而對資料進行了嚴格的保護。
流式查詢處理
ContainerDB透過在Gate層實現基於優先順序的歸併排序提供了快速流式查詢的功能,在進行大批次資料查詢時,能瞬時返回部分查詢結果資料,極大提高客戶體驗。
無感知資料遷移
ContainerDB透過在交叉在Window函式中分別執行部分存量資料複製和增量資料追加的演算法,開發了線上資料遷移和接入工具JTransfer,透過JTransfer可以將傳統MySQL資料庫中的動態資料遷移到ContainerDB中,當ContainerDB中的資料與源MySQL中的資料的lag小於5秒時,首先會將源MySQL停寫,待lag變為0時將源MySQL的域名漂移到Gate叢集,整個遷移過程使用者AppServer無感知。
相容MySQL協議
ContainerDB完全相容MySQL協議,支援標準MySQL客戶端和官方驅動程式接入,並且支援大部分ANSI SQL語法。
路由規則透明
ContainerDB與使用者之間透過Gate叢集進行連線,Gate根據使用者傳送的查詢語句形成的語法樹和查詢執行計劃得到查詢中涉及到的所有表,並根據Topology中的後設資料資訊獲得各個表的分片資訊,最後結合語句中的Join中的關聯條件和Where字句中的謂詞資訊,將查詢或者寫入路由到正確的分片。整個過程都是Gate自動完成的,對使用者完全透明。
自助化服務
ContainerDB將對資料庫服務的例項化、DDL/DML執行、分片升級和擴容等功能抽象成為獨立的介面,並藉助於流程引擎提供了流程化的完全自助的使用者接入服務,使用者申請資料庫服務成功後,ContainerDB會將資料庫訪問口令自動推送到使用者郵箱。
過去已去,未來已來。
我們後續會更多的從使用者的角度去思考資料庫能夠產生的價值。我們相信京東以後的資料庫服務會:
More Smart:我們會基於各個資料庫例項中CPU/記憶體/硬碟等各種不同資源的監控資料進行深度學習和聚類分析,分析出各個不同資料庫例項的傾向資源,並智慧化調高每個資料庫例項傾向資源的限制並調低非傾向資源的限制。
More Quick:我們會實時分析宿主機和容器的對應關係、各個容器的限制引數以及各個容器的歷史資源增長速率,預先對容器所在宿主機碎片進行整理,從而儘量保證各個容器以垂直升級的方式實現擴容,從而極大地加快擴容速度。
More Cheap:我們會提供完全自主研發的儲存引擎,計劃實現查詢引擎與儲存引擎的整合,並提供多模型資料庫引擎,從而實現多種資料模型的統一,極大節省資料庫服務所需資源以及研發成本。
More Friendly:無論是ContainerDB還是我們自主研發的多模型資料庫,我們都會完全相容MySQL協議及語法,從而使得現有應用的遷移成本趨近於0。
More Open:ContainerDB會在經過京東內部的各種場景的磨練之後會擁抱開源,並希望與業界各位同仁一起將ContainerDB不斷完善。同時我們後續的多模型資料庫最終也會貢獻給開源社群,並期待其服務於業界。