您的位置:首頁>科技>正文

從0到1,原來滴滴DB自動化運維是這樣實踐的

本文根據朱進卓老師在2018年4月14日【3306π 北京站】現場演講內容整理而成。

講師介紹:

▲朱進卓:滴滴資深DBA

朱進卓主要負責滴滴專車、快車等核心業務線資料庫維護,

資料庫架構設計、優化、高可用維護, 滴滴內部自動化平臺RDS部分模組開發。 先後就職於搜狐暢遊和金山, 技術涉獵MySQL 、Redis、MongoDB、OpenStack、Python、Go。

滴滴現在主要使用的資料庫是MySQL。 滴滴的業務擴展很快, 目前DB伺服器大致有3000-4000台, 實例就很恐怖了, 整體有7、8千。 在這種情況, 靠純人工去做運維是不可能的了, 所以說我今天就和大家分享一下我們自動化運維從0到1的實踐。

分享大綱:

1.滴滴DB架構介紹

2.主要工作內容

3.主要關注模組

4.自動化模組

5.後續補充項

一.滴滴DB架構介紹

一般來說, 自動化運維都會根據自己原有的架構來設計自動化運維平臺, 上圖是滴滴DB的架構圖, 最上面是TGW LVS, 也就是大家所熟悉的VIP, 接下來是代理層dbproxy。 代理層下面是MySQL的主從關係, 一般情況是一主、一備主和一個從庫, 如果讀取操作多, QPS會比較高, 從庫也需相應的增多。

同時還要有MySQL高可用的監控來應對主庫掛了等等的異常情況。 運維監控, 我們是使用最常見的ZABBIX來做的。 除此之外, 我們還做了備份模組和性能優化的模組。

dbproxy相當於一個入口,

連接應用, 它是分散式的, 因此每臺上都會有自己的原始配置, 所有的訪問DB的流量都要經過dbproxy層, dbproxy會記錄正常的訪問日誌, 還有一些錯誤日誌, 例如沒有加白名單或者是SQL語法錯誤等等都會在dbproxy層攔截, 產生錯誤日誌。

上圖的架構就是我們在做自動化運維的初始部署, 我們希望能夠完成從業務申請到部署完成的一系列連貫動作。

二.主要工作

我們平時的工作內容如上圖所示, 基本包括部署、工單處理、擴容拆分、監控報警處理以及其它任務。

一周時間, RD申請30—50個實例在我們的工作中是很常見的, 這時如果沒有自動化運維, 單純靠自己手工部署的話, 是很消耗時間的;工單處理的工作內容基本就是做一些DDL、表結構的變更, 白名單以及其它需求;隨著業務的發展, 資料量會猛增, 由於單機磁片的存儲是有限的, 這時我們就要思考擴容、拆分的問題了, 還有一種情況是磁片可能足夠存儲, 但是你的TPS/QPS單機可能撐不住, 這時也要去做擴容;監控報警處理指的是我們前面提到的SQL錯誤,

白名單沒有加以及其它一些報警。

其中, 部署和工單處理是我們日常工作的重頭, 其占比大約為70%。 但是這一部分工作很容易自動化, 一旦實現自動化, 我們的工作強度會大大降低。

其實我們的工作痛點前面也提到了一部分, 第一個就是因為量大, 我們每週都會有很多的新申請,所以這部分工作的自動化是迫在眉睫的。

其次,我們的業務還有一個特點就是峰值比較集中,因為打車一般都集中發生在早高峰或晚高峰,所以系統的瓶頸也集中在這兩個時間段。

第三個是資料庫的延時,業務一般都會有超時時間的設置,資料庫的延時是非常敏感的,一個查詢進入到資料庫再到返回結果的延時,這裡的延遲指的不是我們平常意義上的主從同步資料的延時,指的是對業務SQL的回應時間,線上DDL的表結構修改也會影響到延時。

最後就是工作的多樣性。

三.主要關注的模組

做自動化運維,之前的模組肯定是不能丟掉的。之前,我們的高可用、資料備份、監控報警、線上DDL系統等重點關注模式是使用PT,現在我們改用了ghost。

在完成整個運維自動化的過程中,我們做的第一步是DBA的自動化運維,其次是資料庫系統服務化,當然現在我們的功能還達不到雲服務商提供的那樣,但是業務如果需要申請一個DB,相關人員在平臺上操作幾步就可以自己完成。

既然要做自動化運維,那麼所有的東西就必須要標準化。我們根據之前的架構做了一些標準化的工作,例如OS初始化的標準化(檔案系統,內核設置,磁片掛載目錄等)和資料庫層面的標準化(設定檔、部署路徑、多實例目錄命名規則以及ID的命名規則)。

這張圖是滴滴DB自動化架構的細節展示。

線上業務系統的最左側是VIP,第二列是代理層中介軟體,第三列是MySQL,在這一層我們一般是用mha來保證MySQL的高可用。第四列是資料匯流排,很多人可能不理解資料匯流排,我舉個簡單的例子,如果乘客或者司機想要查詢歷史訂單,那麼你當然不能直接去線上的訂單庫裡查詢。線上訂單庫一般是按城市來分的,所以你還需要按照司機或乘客的ID將訂單資料雜湊到另一張表裡,並且在這個新的庫裡進行歷史資料的查詢,相當於對資料重新做了一次分發和雜湊。

線上輔助系統主要包括MySQL集群meta資訊、線上DDL、SQL審計、SQL統計等。

自動化運維系統的Web層更多的是前端、介面化的東西,接下來是API層、調度層和執行層。

API層聯動著很多操作,假設我現在去Web端申請了一個實例,那麼接下來API層就會有一些動作,例如新建實例、新建MySQL集群、新建dbproxy,之後還需要做備份相關的東西。

四.自動化模組

中介軟體的擴容指的是dbproxy層,可能我們最開始只有三台,但是隨著訪問的增多,它本身也需要擴容。

DB層,就如我們剛才看到的mha那一塊,一開始我們可能申請了三台,一個主庫、一個備主庫和一個從庫,我們需要進行部署、擴容和備份。上圖中的拆分主要是根據QPS/TPS來進行拆分,還有就是一些故障機的下線。

資料連結層,這一層做的功能還是比較強大的,因為好多東西都依賴這一層。我們是利用了開源的canal+Kafka+zookeeper,對資料重新做雜湊,比如我上游可能是根據城市來分表的,那我下游就有可能把多個城市的表聚合起來。

線上輔助系統就是之前說的備份系統、高可用、SQL審計以及它的優化建議,監控報警、定時任務、資料連結的耗時分析。

定時任務怎麼理解?實際應用可能會有一些按天數分表的情況,一般來說,業務肯定不會每天去建一個新表,所以這些操作都會由定時任務調度來處理,還有一些監控腳本、備份腳本、歷史資料刪除腳本都會在定時任務裡。

資料連結的耗時分析,如果前端要訪問資料庫,那麼需要經過的層比較多,先要通過dbproxy,再要通過MySQL,MySQL回包……這整個過程中,哪個過程是最耗時的?我們會繪製一個整個過程的時間序列圖,這樣就可以一目了然的看出哪裡耗時最嚴重。

自動化運維系統的調度層我們是基於Python和tornado,底層執行是用saltstack。

上面這張圖片有tornado和saltstack的官網連結,大家可以參考。

下面我再講幾個案例。根據架構,我們首先要去細分需要做哪些東西?分析完之後,我們還需要從中挑選出更為重要的模組,例如佔用工時較久的部署,優先自動化。

線上DDL是一個比較重要的模組,它的業務峰值是比較集中的,有可能一個表是非常大的,你想避開高峰期,例如想在晚10點到早8點做完,但是有可能是做不完的。時間跨度大一直是線上DDL的一個痛點,而且有些大表的業務修改是很敏感的。

線上DDL的一般邏輯就是先創建一個空表,修改空表的表結構,把歷史資料和增量資料同步到新表中,最後一步就是rename table,對新表和舊表做一次交換。

我們之前資料量不是很大的時候使用的是pt。pt的話,歷史資料一般就是通過INSERT LOW_PRIORITY IGNORE INTO ,而增量資料是通過trigger來做的。

但是這種方法會有個問題,你對原表的操作都會通過觸發器來觸發一個相應的操作,它對於QPS來說是雙倍的,而且是同時。例如你在對一個表訪問,它上面100多個TPS,對於業務來說,正常情況可能是100毫秒或者是幾毫秒的耗時,但你在修改這個的時候,耗時會很長,甚至有可能會訪問不成功。

後來,我們經過調研就選擇了inception+ghost,沒有觸發器。它的原理是先去建一個新表,對新表進行表結構的修改,再去解析一個從庫對舊表操作的binlog來重播增量資料的處理,原有的老資料也是通過單個chunk的方式複製到新表中,新資料通過重播從庫對舊表的操作binlog來回寫到新表中,所以對於主庫的壓力比較低,主庫上舊表和新表的寫入也是非同步的,避免了觸發器同步執行的弊端,比如新加一個欄位或者修改欄位的類型。

當然它也是有版本反覆運算的,大家可以 根據自己的需求來進行修改。

這個是前面提到的saltstack實例,如何通知底層來做相關的新建任務?其實就是通過saltstack來去調用底層執行。

假設我現在要新建一個MySQL的主從實例,最上面是服務名稱,這個服務名稱就是一般來說都是以用途來命名,接下來是選擇版本和port,還要選擇主庫、備主庫、從庫,如果你的QPS非常高,那三台機器是不夠的,需要增加幾台,直接加在後面就可以了。

針對MySQL的新建,我們會有一個範本一樣的資料檔案,其中已經包含了mha所需要的使用者資訊,類似於連接資訊、授權等等都會在這個demo的檔裡。

新建MySQL,相當於我先去拷一個範本檔,調用介面,新建埠,這個埠一般來說是多實例的。dst一般是根據你申請的資料庫或者服務名來去定義目的機器的目錄名稱。傳進來之後,就要判斷機器上這個埠是否存在,如果存在的話,是不可以再新建一個同樣的埠。如果不存在的話,我們下一步就是判斷目錄是否存在。

這裡需要強調的一點是,salt是一步一步開始執行的,一旦哪個步驟出現錯誤,那就是直接失敗,不再接著往下繼續了。

原資料的demo資料檔案建好了,下一步就是建立範本的設定檔。設定檔和資料檔案有很多相似之處,都是先去判斷埠是否存在,資料檔案目錄是否存在,創建目錄,salt其實在系統裡面內置了很多命令可供用戶調用,最後判斷MySQL版本來拉取範本設定檔。

因為範本設定檔是通用的,所以下一步就是修改設定檔,比如port資訊,datadir、binlogdir等等。這個部分其實也是一個salt模組,其實就是把範本檔中的port替換成你傳進來的port。

下一步就是啟動MySQL,資料檔案拉取過來了,設定檔修改完成了,直接去啟動MySQL就可以了。

啟動之後,因為你建立的是一個主從複製關係的集群,假設現在建立了三個實例,而複製關係還沒有配置,這個地方就是相當於傳一些參數來配置複製關係的。

以上是MySQL新建的過程,dbproxy的新建過程大致也是差不多的。一般都會做demo的東西拉取過來,之後修改設定檔,再去啟動。

五.後續補充項

MySQL、dbproxy和mha 的搭建備份都已經實現自動化了。但是我們現在還有一些東西沒有實現自動化。

資源管理和分配,申請一個實例,資源池中的機器如何選擇還沒有自動化。

VIP自動分配其實在我司是運維來做的,VIP是綁定在後端dbproxy機器上的,沒有自動化的原因是因為我們不太好推動。

細細微性的監控報警,伺服器的動態或者資料庫的連接資訊或者狀態,你是可以看到的。但是如果線上新上線了一個東西,但是庫裡還沒有新加欄位。如果是不重要的模組,可能直接跑一個腳本。我們希望做到dbproxy層的報警都可以直接發給集群的創建者。

慢查分析,優化建議,現在我們有搜集慢查分析的相關資訊,但是沒有做到自動化的頁面上去。

我們每週都會有很多的新申請,所以這部分工作的自動化是迫在眉睫的。

其次,我們的業務還有一個特點就是峰值比較集中,因為打車一般都集中發生在早高峰或晚高峰,所以系統的瓶頸也集中在這兩個時間段。

第三個是資料庫的延時,業務一般都會有超時時間的設置,資料庫的延時是非常敏感的,一個查詢進入到資料庫再到返回結果的延時,這裡的延遲指的不是我們平常意義上的主從同步資料的延時,指的是對業務SQL的回應時間,線上DDL的表結構修改也會影響到延時。

最後就是工作的多樣性。

三.主要關注的模組

做自動化運維,之前的模組肯定是不能丟掉的。之前,我們的高可用、資料備份、監控報警、線上DDL系統等重點關注模式是使用PT,現在我們改用了ghost。

在完成整個運維自動化的過程中,我們做的第一步是DBA的自動化運維,其次是資料庫系統服務化,當然現在我們的功能還達不到雲服務商提供的那樣,但是業務如果需要申請一個DB,相關人員在平臺上操作幾步就可以自己完成。

既然要做自動化運維,那麼所有的東西就必須要標準化。我們根據之前的架構做了一些標準化的工作,例如OS初始化的標準化(檔案系統,內核設置,磁片掛載目錄等)和資料庫層面的標準化(設定檔、部署路徑、多實例目錄命名規則以及ID的命名規則)。

這張圖是滴滴DB自動化架構的細節展示。

線上業務系統的最左側是VIP,第二列是代理層中介軟體,第三列是MySQL,在這一層我們一般是用mha來保證MySQL的高可用。第四列是資料匯流排,很多人可能不理解資料匯流排,我舉個簡單的例子,如果乘客或者司機想要查詢歷史訂單,那麼你當然不能直接去線上的訂單庫裡查詢。線上訂單庫一般是按城市來分的,所以你還需要按照司機或乘客的ID將訂單資料雜湊到另一張表裡,並且在這個新的庫裡進行歷史資料的查詢,相當於對資料重新做了一次分發和雜湊。

線上輔助系統主要包括MySQL集群meta資訊、線上DDL、SQL審計、SQL統計等。

自動化運維系統的Web層更多的是前端、介面化的東西,接下來是API層、調度層和執行層。

API層聯動著很多操作,假設我現在去Web端申請了一個實例,那麼接下來API層就會有一些動作,例如新建實例、新建MySQL集群、新建dbproxy,之後還需要做備份相關的東西。

四.自動化模組

中介軟體的擴容指的是dbproxy層,可能我們最開始只有三台,但是隨著訪問的增多,它本身也需要擴容。

DB層,就如我們剛才看到的mha那一塊,一開始我們可能申請了三台,一個主庫、一個備主庫和一個從庫,我們需要進行部署、擴容和備份。上圖中的拆分主要是根據QPS/TPS來進行拆分,還有就是一些故障機的下線。

資料連結層,這一層做的功能還是比較強大的,因為好多東西都依賴這一層。我們是利用了開源的canal+Kafka+zookeeper,對資料重新做雜湊,比如我上游可能是根據城市來分表的,那我下游就有可能把多個城市的表聚合起來。

線上輔助系統就是之前說的備份系統、高可用、SQL審計以及它的優化建議,監控報警、定時任務、資料連結的耗時分析。

定時任務怎麼理解?實際應用可能會有一些按天數分表的情況,一般來說,業務肯定不會每天去建一個新表,所以這些操作都會由定時任務調度來處理,還有一些監控腳本、備份腳本、歷史資料刪除腳本都會在定時任務裡。

資料連結的耗時分析,如果前端要訪問資料庫,那麼需要經過的層比較多,先要通過dbproxy,再要通過MySQL,MySQL回包……這整個過程中,哪個過程是最耗時的?我們會繪製一個整個過程的時間序列圖,這樣就可以一目了然的看出哪裡耗時最嚴重。

自動化運維系統的調度層我們是基於Python和tornado,底層執行是用saltstack。

上面這張圖片有tornado和saltstack的官網連結,大家可以參考。

下面我再講幾個案例。根據架構,我們首先要去細分需要做哪些東西?分析完之後,我們還需要從中挑選出更為重要的模組,例如佔用工時較久的部署,優先自動化。

線上DDL是一個比較重要的模組,它的業務峰值是比較集中的,有可能一個表是非常大的,你想避開高峰期,例如想在晚10點到早8點做完,但是有可能是做不完的。時間跨度大一直是線上DDL的一個痛點,而且有些大表的業務修改是很敏感的。

線上DDL的一般邏輯就是先創建一個空表,修改空表的表結構,把歷史資料和增量資料同步到新表中,最後一步就是rename table,對新表和舊表做一次交換。

我們之前資料量不是很大的時候使用的是pt。pt的話,歷史資料一般就是通過INSERT LOW_PRIORITY IGNORE INTO ,而增量資料是通過trigger來做的。

但是這種方法會有個問題,你對原表的操作都會通過觸發器來觸發一個相應的操作,它對於QPS來說是雙倍的,而且是同時。例如你在對一個表訪問,它上面100多個TPS,對於業務來說,正常情況可能是100毫秒或者是幾毫秒的耗時,但你在修改這個的時候,耗時會很長,甚至有可能會訪問不成功。

後來,我們經過調研就選擇了inception+ghost,沒有觸發器。它的原理是先去建一個新表,對新表進行表結構的修改,再去解析一個從庫對舊表操作的binlog來重播增量資料的處理,原有的老資料也是通過單個chunk的方式複製到新表中,新資料通過重播從庫對舊表的操作binlog來回寫到新表中,所以對於主庫的壓力比較低,主庫上舊表和新表的寫入也是非同步的,避免了觸發器同步執行的弊端,比如新加一個欄位或者修改欄位的類型。

當然它也是有版本反覆運算的,大家可以 根據自己的需求來進行修改。

這個是前面提到的saltstack實例,如何通知底層來做相關的新建任務?其實就是通過saltstack來去調用底層執行。

假設我現在要新建一個MySQL的主從實例,最上面是服務名稱,這個服務名稱就是一般來說都是以用途來命名,接下來是選擇版本和port,還要選擇主庫、備主庫、從庫,如果你的QPS非常高,那三台機器是不夠的,需要增加幾台,直接加在後面就可以了。

針對MySQL的新建,我們會有一個範本一樣的資料檔案,其中已經包含了mha所需要的使用者資訊,類似於連接資訊、授權等等都會在這個demo的檔裡。

新建MySQL,相當於我先去拷一個範本檔,調用介面,新建埠,這個埠一般來說是多實例的。dst一般是根據你申請的資料庫或者服務名來去定義目的機器的目錄名稱。傳進來之後,就要判斷機器上這個埠是否存在,如果存在的話,是不可以再新建一個同樣的埠。如果不存在的話,我們下一步就是判斷目錄是否存在。

這裡需要強調的一點是,salt是一步一步開始執行的,一旦哪個步驟出現錯誤,那就是直接失敗,不再接著往下繼續了。

原資料的demo資料檔案建好了,下一步就是建立範本的設定檔。設定檔和資料檔案有很多相似之處,都是先去判斷埠是否存在,資料檔案目錄是否存在,創建目錄,salt其實在系統裡面內置了很多命令可供用戶調用,最後判斷MySQL版本來拉取範本設定檔。

因為範本設定檔是通用的,所以下一步就是修改設定檔,比如port資訊,datadir、binlogdir等等。這個部分其實也是一個salt模組,其實就是把範本檔中的port替換成你傳進來的port。

下一步就是啟動MySQL,資料檔案拉取過來了,設定檔修改完成了,直接去啟動MySQL就可以了。

啟動之後,因為你建立的是一個主從複製關係的集群,假設現在建立了三個實例,而複製關係還沒有配置,這個地方就是相當於傳一些參數來配置複製關係的。

以上是MySQL新建的過程,dbproxy的新建過程大致也是差不多的。一般都會做demo的東西拉取過來,之後修改設定檔,再去啟動。

五.後續補充項

MySQL、dbproxy和mha 的搭建備份都已經實現自動化了。但是我們現在還有一些東西沒有實現自動化。

資源管理和分配,申請一個實例,資源池中的機器如何選擇還沒有自動化。

VIP自動分配其實在我司是運維來做的,VIP是綁定在後端dbproxy機器上的,沒有自動化的原因是因為我們不太好推動。

細細微性的監控報警,伺服器的動態或者資料庫的連接資訊或者狀態,你是可以看到的。但是如果線上新上線了一個東西,但是庫裡還沒有新加欄位。如果是不重要的模組,可能直接跑一個腳本。我們希望做到dbproxy層的報警都可以直接發給集群的創建者。

慢查分析,優化建議,現在我們有搜集慢查分析的相關資訊,但是沒有做到自動化的頁面上去。

Next Article
喜欢就按个赞吧!!!
点击关闭提示