容器化MYSQL集群在Uber系統中的應用

2021-09-22 23:48:38 字數 3818 閱讀 3760

本文講的是容器化mysql集群在uber系統中的應用【編者的話】uber使用的schemaless儲存系統支撐了uber最重要的服務,如,mezzanine等。schemaless 是乙個構建在mysql集群上,可擴充套件高可用的資料儲存。但管理uber資料量龐大的資料庫集群服務需要應用docker技術。

當集群節點數為16個時,集群管理非常容易,但若集群規模超過1000,並執行了4000多個資料庫服務,就需要另一種工具了。之前所有的集群都由 puppet來管理。大量的臨時指令碼,以及人工操作已無法滿足uber業務擴充套件的要求。我們開始尋找乙個管理規模遞增的mysql集群工具,工具必須具備以下基本需求:

解決方案被命名為schemadock,採用docker容器執行mysql,目標是將管理集群拓撲定義在配置檔案中。集群拓撲定義了mysql集群,例如,乙個集群內應用3個資料庫,其中乙個是主,**應用這些拓撲定義在每個資料庫上,乙個集中服務用來維護和監控各例項的目標狀態,並及時糾正偏差。

schemadock 由幾個部件組成,docker是其中一小部分但卻是最重要的部分。轉型到這種可擴充套件的方案需要付出相當大的努力,本文將介紹docker如何幫助系統達成目標:

容器化程序可實現不同版本及配置的mysql程序執行在同一臺主機上,也可以在同乙個主機上配置不同小集群用來實現在更少的主機上執行同樣規模集群的目的。最終,可實現不依賴puppet,並且所有主機都可配置成一樣的角色。

對於docker自身,工程師可在docker上構建微服務。關於docker已經有大量的工具及知識累積,雖然docker肯定不是最好的,但目前來講是最佳選擇。

為何不使用docker呢?

選擇docker包括全虛擬化、lxc容器、或通過類似puppet工具來管理執行在主機上的mysql程序。對我們而言,選擇docker是因為簡單,因為它很適合現有的架構。但如果沒準備好使用docker,而只想使用mysql,這便是乙個巨大的工程:包括完成映象建立、發布、監控、公升級docker、日誌收集、網路設定、等等工作。

這意味著,若要使用大量資源,就只能選擇docker。此外,docker只是一種技術,而不是乙個解決方案。在uber的方案中詳細規劃了乙個以docker為核心部件的大型系統,用於管理 mysql資料庫。但並不是所有公司都像uber一樣廣泛使用docker,因為一些更簡單的方案例如puppet 或ansible可能更適合。

容器的角色通過環境變數來定義。而這個角色僅負責接收初始化資料,docker映象本身不包含任何建立複製拓撲、狀態檢查等邏輯。由於這些邏輯比mysql 本身變動更為頻繁。因此需要花大力氣實現分離。

mysql 資料目錄通過主機的檔案系統實現掛載,意味著docker沒有任何寫開銷,實際部署時將mysql 的配置考入了映象來固化配置。也就是說,當修改配置時無法生效。若容器因為某種原因宕機,不是重啟容器,而是刪除容器,再使用同樣的引數,從最新版本映象(若目標變更,則從新映象)重新建立乙個新容器,並啟動它。

這種做法的好處是:

uber 通過建立映象支援微服務架構,此架構從資料中心複製映象到本地啟用註冊使用。

但在乙個節點上執行多個容器也有缺點,因為在每個容器之間沒有合適的隔離i/o的功能,乙個容器可能佔滿所有i/o頻寬,導致其他容器故障。docker 1.10 新增了i/o限額功能,但是目前還沒有應用過。不過我們通過降低主機負載和持續監控資料庫效能來預防此問題。

現在我們有乙個可以啟動的docker主或從節點映象,為了啟動這些容器並將它們配置到正確的複製拓撲,每台資料庫節點上需要執行乙個**,用來接收不同節點上的所有資料庫的目標資訊。典型的目標狀態資訊例項如下:

「schemadock01-mezzanine-mezzanine-us1-cluster8-db4」: 

}

這段資訊表明:在節點schemadock01 上需在7335埠上執行乙個 mezzanine 資料庫從節點,並啟動schemadock30:7335的資料庫主節點。這裡的『all』引數是說該節點上只執行資料庫,因此需要分配所有的記憶體給資料庫使用。

建立目標狀態對另乙個請求來說就是乙個會話,下一步:主機上執行的**接收到這個資訊後儲存在本地,並開始處理。

處理方式是乙個週期為30秒的無線迴圈,類似每30秒執行puppet 一樣。通過以下步驟每隔30秒迴圈檢查系統實際狀態同目標狀態記錄的資訊是否一致:

檢查容器是否已經執行。若沒有,則根據配置建立乙個並啟動;

檢查容器是否有複製拓撲。若無,則修復:

基於角色檢查mysql各種 引數(例如:read_only 、 super_read_only、 sync_binlog等),如:主節點可寫,從節點為唯讀模式等等。此外,為了降低從節點的執行負載可關閉日誌同步等相關引數。

啟停任何支援的容器功能,例如關閉 pt-heartbeat 心跳檢測和pt-deadlock-logger死鎖檢測。

注意:uber特別認同這種單程序只做單用途的容器設計理念,因為不用對已執行的容器進行重新配置,更容易控制或公升級。

何時何地只要發生錯誤,程序只用報錯或者退出。然後嘗試重新啟動。但架構會確保在各個**之間儘量減少互動,也就是說集群不關心執行順序。例如,在建立乙個新的集群時,手工建立需以下步驟:

建立mysql 主節點並等待生效;

建立第乙個從節點並連線到主節點;

剩餘的從節點重複以上步驟。

必然會發生一些意外,但我們並不關心嚴格的執行順序,只要最終狀態達到我們設定的目標就行:

「schemadock01-mezzanine-cluster1-db1」: 

},「schemadock02-mezzanine-cluster1-db2」: 

},「schemadock03-mezzanine-cluster1-db3」: 

}

這個資訊將被隨機推送到相關**,並啟動執行。為達到最終目標狀態,會有一些重試操作。通常經過幾次重試後都會最終達到目標狀態,但有一些操作可能需要100多次的重試。例如,從節點最先被啟動,無法連線到主節點,然後不得不重啟。因為主節點啟動並執行需要一段時間,所以從節點需要重啟很多次。

大部分主機執行的是帶裝置對映的docker 1.9.1版本使用lvm實現儲存管理。應用lvm進行裝置對映比使用loopback的執行效能優異得多。裝置對映本身存在很多效能和可靠方面的問題,但是若是選擇使用 aufs 或overlayfs 也存在大量問題。目前在社群中關於儲存的選型存在很大的爭議。目前為止,overlayfs 獲得了一定的認可,執行比較穩定,因此我們確定了選擇它,並將docker的版本公升級到1.12.1。

docker公升級的痛點之一是需要重啟所有的容器。這意味著公升級時沒有主節點,公升級程序必須可控。希望docker1.12.1是最後乙個要擔心這個問題的版本,1.12 已經有乙個選項可以控制重啟和公升級docker 守護程序時無需重啟容器。

docker的每個版本都有一些進步和新特性,同時也會有一些漏洞。1.12.1比以往的版本都要有優勢,但也有以下限制:

我們在uber的集群儲存上提了大量需求:

一台主機執行多個容器

自動單點登入

現在,我們已經可以通過簡單的工具和統一的ui介面進行日常維護,而無需登入主機。

在一台主機上執行多個容器提公升主機利用率。在可控模式下進行整體公升級。docker已經為我們的技術架構提公升了很多,也支援測試環境下整體集群的本地化公升級,及試執行所有作業系統程序。

從2023年開始uber實施系統docker化的遷移,目前已執行了1500多個生產伺服器(僅mysql ),並執行了2300多個mysql 資料庫。

雖然應用docker是技術上的重大成功,也使得uber架構進步更快。但比schemadock專案本身意義更大的是,整個出行資料倉儲,幾乎每天百萬次出行記錄已經執行在了docker上的mysql 中。另乙個角度想,docker成為使用uber出行打車的關鍵。

原文發布時間為:

2017-01-26

chilly

容器化mysql集群在uber系統中的應用

Neo4j集群容器化部署

core servers 10.110.10.11,10.110.10.12,10.110.10.13 read replicas 10.110.10.14,10.110.10.15,10.110.10.16 neo4j圖資料庫分布式架構圖 詳細可參考官方文件 分別在伺服器10.110.10.11,...

Neo4j集群容器化部署

core servers 10.110.10.11,10.110.10.12,10.110.10.13 read replicas 10.110.10.14,10.110.10.15,10.110.10.16 neo4j圖資料庫分布式架構圖 詳細可參考官方文件 分別在伺服器10.110.10.11,...

在 Docker 中重建 MySQL 集群

本文記錄了使用重建集群的過程 1.關閉並移除所有資料庫 在 windows 環境中,通過 xshell 連線到各個節點然後分別執行 docker stop mysql docker rm f mysql2.選擇主節點bash mysql start.sh 首先執行mysql的映象,mysql sta...