1. 程式人生 > >系統技術非業餘研究 » 低成本和高效能MySQL雲資料的架構探索

系統技術非業餘研究 » 低成本和高效能MySQL雲資料的架構探索

該文已在《程式設計師》2012年10期上發表。

MySQL作為一個低成本、高效能、可靠性好而且開源的資料庫產品,在網際網路企業應用非常廣泛,例如淘寶網有數千臺MySQL伺服器的規模。雖然近兩年來NoSQL的發展很快,新產品層出不窮,但在業務中應用NoSQL對開發者來說要求比較高,而MySQL擁有成熟的中介軟體、運維工具,已經形成一個良性的生態圈等,因此從現階段來看,MySQL佔主導性,NoSQL為輔。
在過去一年時間裡,我們(阿里集團核心系統資料庫團隊)在MySQL託管平臺方向做了大量工作,設計和實現了一套UMP(Unified MySQL Platform)系統,提供低成本和高效能的MySQL雲資料服務。開發者從平臺上申請MySQL例項資源,通過平臺提供的單一入口來訪問資料,UMP系統內部維護和管理資源池,以對使用者透明的形式提供主從熱備、資料備份、遷移、容災、讀寫分離、分庫分表等一系列服務。平臺通過在一臺物理機上執行多個MySQL例項的方式來降低成本,並且實現了資源隔離,按需分配和限制CPU、記憶體和IO資源,同時支援不影響提供資料服務的前提下根據使用者業務的發展動態的擴容和縮容。

架構的演變
UMP系統第一版基於mysql-proxy 0.8版修復若干bug,並對proxy外掛中管理使用者連線和資料庫連線的狀態機流程進行一些修改,同時編寫Lua指令碼實現去中心資料庫獲取使用者認證資訊和後臺資料庫地址,對使用者進行驗證,建立到後臺資料庫的連線和轉發資料包等邏輯。

圖1 UMP系統的第一版採用MySQL Proxy

在開發和部署第一版的過程中,我們逐漸認識到幾個問題:

首先,mysql-proxy 0.8版對多執行緒的支援比較簡單粗暴,多個工作執行緒共享同一個訊息佇列,同時監聽著同一個socketpair通道,當有新事件進入訊息佇列後,socketpair會被寫入一個位元組,所有休眠中的執行緒都會被喚醒,去競爭一個互斥鎖從訊息佇列中取任務。這種實現一是造成“驚群”現象,多個執行緒被喚醒但只有一個執行緒需要去任務,二是任務的CPU親緣性比較差,在同一個狀態機上觸發的事件會在多個處理器上來回切換執行。此外,mysql-proxy中還使用了全域性Lua鎖,同時僅允許一個工作執行緒執行Lua指令碼(計劃在0.9版本中改進),因此mysql-proxy多執行緒模式下的效能遠不能同CPU核數保持線性增長,甚至在16核上的效能還不如4核。而使用單程序模式時,一臺物理機上需要部署多個程序才能有效利用機器的處理能力,但給部署、監控和服務的升級帶來麻煩。
其次,限於mysql-proxy的框架,功能上不容易擴充套件,實現使用者的連線數限制、QPS限制、以及主從切換、讀寫分離、分庫分表等一系列功能比較困難。
最後,mysql-proxy的社群近些年來並不活躍,而且C語言對開發者功底的要求比較高,很難要求團隊所有成員協同開發出兼顧優雅和正確性的程式碼。
因此我們決定用Erlang語言重新編寫proxy伺服器,替換了原有的mysql-proxy模組。目前整個專案擁有5萬行Erlang原始碼,3萬行C/C++原始碼,2萬行其他語言原始碼。

為什麼選擇Erlang語言
Erlang是一個結構化的、動態的、函式式的程式語言。常見的一個說法是Erlang是面向併發的(concurrent-oriented),這主要指Erlang在語言中定義了Erlang程序的概念和行為(下文中凡是“Erlang程序”都是指Erlang語言中定義的程序,以區分於大家熟悉的作業系統程序),和作業系統的程序/執行緒相比,Erlang程序同樣是併發執行的單位,但特別的輕量級,它是在Erlang虛擬機器內管理和排程的“綠程序”,即使用者態程序。舉個例子,在關閉了HiPE和SMP支援的Erlang虛擬機器中,一個新建立的程序佔用的記憶體僅為309個字(word,64位伺服器上為8個位元組),其中233個字為堆空間(包含棧),建立和結束一個程序的代價約耗時1~3微秒,而一個Erlang虛擬機器中可以同時支援幾十萬甚至更多個程序。


圖2 Erlang的輕量級程序

說到Erlang語言,就必須提及OTP(Open Telecom Platform,開放電信平臺),OTP是用於開發分散式的、高容錯性的Erlang應用程式的框架與平臺。例如,一個Erlang節點連線並註冊到Erlang叢集上,發現叢集中的其他節點,與它們進行RPC通訊,都在OTP裡的kernel服務中實現的。OTP和Erlang語言關係如此緊密以至於兩者通常合稱為Erlang/OTP,因此從嚴格的意義上來講,應該說我們選擇了Erlang/OTP為主來構造UMP系統。Erlang/OTP很好的抽象了開發一個分散式的、高容錯性的應用程式所需的要素,包括:網路程式設計框架、序列化和反序列化、容錯、熱部署。
為了支援併發,伺服器端多采用多程序/多執行緒模型,即每個程序/執行緒處理一個客戶端連線,受限於作業系統資源,每臺伺服器可以處理的併發連線數並不高,同時由於程序/執行緒上下文切換開銷,系統的效能會受到影響。而開發高併發、高效能的伺服器一般採用事件驅動的狀態機模型,底層採用非阻塞I/O(Linux中的epoll,BSD系統中的kqueue,Java中的nio)或者非同步I/O,或者採用非同步的事件通知的I/O框架,例如C/C++下的ACE、boost::asio、libevent,Java下的MINA等,在業務層則使用狀態機來表示每個客戶端連線,通過I/O事件、超時事件驅動著狀態機進行跳轉,每個程序/執行緒可以處理成千上萬個客戶端連線。事件驅動的狀態機模型和多程序/多執行緒模型相比雖然併發量更大、效能更好,但是把業務邏輯表達成狀態機是一件困難的事情,相比而下,多程序/多執行緒模型中業務邏輯可以實現為順序執行的程式碼,開發起來要簡單的多。
Erlang/OTP中的網路程式設計模型則結合了兩者的優點,每個Erlang程序處理一個客戶端連線,業務邏輯是順序執行的。而Erlang程序是極輕量級的,可以認為每個Erlang程序是一個狀態機,堆和棧上的資料是這個狀態機的狀態,而Erlang程序收到資料包或是其他程序發來訊息後執行處理例程相當於狀態機的跳轉,因此也具有高併發和高效能的優勢。
Erlang/OTP定義了“external term format”協議將Erlang資料結構與二進位制串相互轉化,用C實現在Erlang虛擬機器中,跨節點通訊時遵從這個協議。因此,開發者無需額外考慮序列化和反序列化的問題。
至於容錯,Erlang程序的資料空間是相互隔離的,沒有共享記憶體,因此一個Erlang程序崩潰不會影響其他Erlang程序的執行,更不會造成Erlang虛擬機器崩潰。OTP還提供了監督樹機制和heart模組,前者在監控到Erlang程序崩潰時進行故障恢復,後者發現Erlang虛擬機器失去響應時重啟程式。
Erlang/OTP提供熱部署方式,可以避免服務升級時造成不可用時間。此外,OTP還提供了一些在系統執行時觀察系統狀態的工具,例如lcnt工具,可以統計虛擬機器內部的鎖使用次數和衝突次數,指導系統的優化。

當前系統架構
在設計UMP系統時,我們遵循了以下幾條原則:
l 系統對外保持單一入口,對內維護單一的資源池。
l 保證服務的高可用性,消除單點故障。
l 保證系統是彈性可伸縮的,可以動態的增加、刪減計算與儲存節點。
l 保證分配給使用者的資源也是彈性可伸縮的,資源之間相互隔離。

UMP系統中的角色包括:controller伺服器、proxy伺服器、agent伺服器、API/Web伺服器、日誌分析伺服器、資訊統計伺服器。
依賴的開源元件有:Mnesia、LVS、RabbitMQ、ZooKeeper

圖3當前UMP系統架構圖

Mnesia是OTP提供的分散式資料庫,與MySQL NDB出自同門,都是上世紀90年代中期Ericsson為電信業務研發的資料產品。Mnesia支援事務,支援透明的資料分片,利用兩階段鎖實現分散式事務,可以線性擴充套件到至少50個節點。從CAP理論的角度上來說,Mnesia更傾向於犧牲可用性來換取強一致性,屬於CP陣營,但它也提供了髒讀、髒寫操作,可以繞過事務管理去操作資料,這時不保證一致性,這又類似於AP的系統。在工程實踐中,我們用事務去修改關鍵資料例如路由表,而用髒寫介面去寫非關鍵資料例如使用者的狀態資訊,讀取資料用髒讀介面。
Controller伺服器向UMP叢集提供各種管理服務,實現元資料儲存、叢集成員管理、MySQL例項管理、故障恢復、備份、遷移、擴容等功能。Controller伺服器上運行了一組mnesia分散式資料庫服務,系統的元資料比如叢集成員,使用者的配置和狀態資訊,以及使用者名稱到後端MySQL例項地址的對映關係(路由表)等都儲存在mnesia裡,其它伺服器元件通過傳送請求到controller伺服器獲取使用者資料。為了達到高可用性,系統中會部署多臺controller伺服器,它們會通過ZooKeeper提供的分散式鎖演算法選舉出一個leader,這個leader負責排程和監控各種系統任務,例如建立和刪除資料庫例項、備份、遷移等。這些系統任務可以分成多個步驟,而且會涉及到系統中的多個元件,例如主庫、從庫、proxy伺服器等,還需要提供失敗時回滾的方法,因此我們採用類似工作流的方式來實現。每個系統任務都是分成多個階段的Erlang程序,每執行完一個步驟跳進入下個步驟之前會把中間狀態持久化到mnesia中,如果任務因為節點故障的原因停止,leader會檢測到並重新發起該任務,任務重啟後會從上一次失敗的“斷點”繼續向下執行。
API/Web伺服器向用戶提供了系統管理介面。它們是基於開源專案Mochiweb與Chicago Boss開發的,Mochiweb提供http/https服務,而Chicago Boss是由Nginx的作者之一Evan Miller開發,提供類似Rails的MVC框架。和Rails比,Erlang開發的框架天生就對併發有很好的支援,每個請求佔用一個輕量級的Erlang程序,而Rails雖然在最近引入了多執行緒安全,但處理每條請求的時候仍然是獨佔整個程序的,因此需要使用多程序模型處理併發請求,通過Phusion Passenger等應用伺服器進行派發。
Proxy伺服器向用戶提供訪問MySQL資料庫的服務,它完全實現了MySQL協議,使用者可以使用已有的MySQL客戶端連線到proxy伺服器,proxy伺服器通過使用者名稱獲取到使用者的認證資訊、資源配額的限制(例如最大連線數、QPS、IOPS等),以及後臺MySQL例項的地址(列表),再將使用者的SQL查詢請求轉發到正確的MySQL例項上。除了資料路由的基本功能外,Proxy伺服器中還實現了資源限制、遮蔽MySQL例項故障、讀寫分離、分庫分表、記錄使用者訪問日誌的功能。Proxy伺服器是無狀態的,伺服器宕機不會對系統中其他伺服器造成影響,只會造成連線到該proxy的使用者連線斷開。多臺Proxy伺服器採用LVS HA方案實現負載均衡,使用者應用重連後會被LVS定向到其他的proxy上。
Agent伺服器部署在執行MySQL程序的機器上,用來管理每臺物理機上MySQL例項,執行建立、刪除、備份、遷移、主從切換等操作,收集和分析MySQL程序的統計資訊、bin log、slow query log。
日誌分析伺服器會儲存和分析Proxy伺服器傳入的使用者訪問日誌,並實現了實時索引供使用者查詢一段時間內的慢日誌和統計報表。資訊統計伺服器定期將採集到的使用者的連線數、QPS數值,以及MySQL例項的程序狀態用RRDtool進行統計,可以畫圖展示到Web介面上,也可以為今後實現彈性的資源分配和自動化的MySQL例項遷移提供依據。
UMP系統中各節點間的通訊(不包括SQL查詢、日誌等大資料流的傳輸,這些還是直接走TCP的)都通過RabbitMQ,作為訊息通訊的中介軟體來使用,來保證訊息傳送的可靠性。ZooKeeper則主要發揮配置伺服器、分散式鎖,以及監控所有MySQL例項的作用。在多個元件的協同作業下,整個系統實現了對使用者透明的容災、讀寫分離、分庫分表功能。系統內部還通過多個小規模使用者共享同一個MySQL例項,中等規模使用者獨佔一個MySQL例項,多個MySQL例項共享同一個物理機的方式實現資源的虛擬化,降低整體成本。在資源隔離方面,通過Cgroup限制MySQL程序資源,以及在proxy伺服器端限制QPS相結合的方法,UMP系統實現了資源虛擬化的同時保障使用者的服務質量。此外,UMP系統綜合運用SSL資料庫連線、資料訪問IP白名單、記錄使用者操作日誌、SQL攔截等技術保護使用者的資料安全。

結束語

UMP系統的一些元件,例如proxy伺服器和日誌分析伺服器,目前已經運用在天貓的聚石塔平臺中,為電商和ISV提供安全的資料雲服務。此外,UMP系統還運用在淘寶的店鋪裝修平臺中,為開發者提供資料服務。下一階段,我們希望UMP系統可以為進一步降低集團內部資料儲存的成本做出貢獻。

附上UMP portal部份截圖:

圖4 MySQL例項情況

圖5 使用者例項管理

圖6 dashboard

祝玩得開心!

Post Footer automatically generated by wp-posturl plugin for wordpress.

相關推薦

系統技術業餘研究 » 成本高效能MySQL資料架構探索

該文已在《程式設計師》2012年10期上發表。 MySQL作為一個低成本、高效能、可靠性好而且開源的資料庫產品,在網際網路企業應用非常廣泛,例如淘寶網有數千臺MySQL伺服器的規模。雖然近兩年來NoSQL的發展很快,新產品層出不窮,但在業務中應用NoSQL對開發者來說要求比較高,而MySQL擁有

系統技術業餘研究 » erlang:send_aftererlang:start_timer的使用解釋

前段時間arksea同學提出這個問題, 因為文件裡面寫的很不明白. erlang:send_after(Time, Dest, Msg) -> TimerRef Time = int() 0 <= Time <= 4294967295 Dest = pid() | RegName

系統技術業餘研究 » Tsung用於壓測MySQL伺服器的指令碼

這個MySQL伺服器壓測的需求是 : 環境: Linux RHEL 5U4 X86-64, 24G記憶體, 16核. MySQL伺服器在xx.232.36.1上。 壓力由最多32個客戶端發起,每個客戶端分別做update, insert, delete操作,概率分別是50%, 30%, 20%

系統技術業餘研究 » 新的工作研究方向

和大家更新下: 做了將近8年資料庫後,我的工作和研究方向將會延伸到虛擬化和計算相關的雲服務,希望能夠和大家一起進步,Happy New Year! 預祝大家玩得開心! Post Footer automatically generated by wp-posturl plugin for w

系統技術業餘研究 » 如何檢視節點的可用控制代碼數目已用控制代碼數

很多同學在使用erlang的過程中, 碰到了很奇怪的問題, 後來查明都是檔案控制代碼不夠用了, 因為系統預設的是每個程序1024. 所以我們有必要在程式執行的時候, 瞭解這些資訊, 以便診斷和預警. 下面的這個程式就演示了這個如何檢視節點的可用控制代碼數目和已用控制代碼數的功能. 首先確保你已經安

系統技術業餘研究 » oprofile抓不到取樣資料問題解決方法

最近有同學反映在某些新機器上做效能調優的時候, oprofile 有時抓不到資料,我之前也遇到這個情況,很是無語,今天特地驗證了下。 # 我們的作業系統和機器配置大概是這樣的: $sudo aspersa/summary # Aspersa System Summary Report ##

系統技術業餘研究 » Erlang match_spec引擎介紹應用

match_spec是什麼呢? A “match specification” (match_spec) is an Erlang term describing a small “program” that will try to match something (either the para

系統技術業餘研究 » Erlang虛擬機器基礎設施dtrace探測點介紹使用

最新的Erlang虛擬機器(R15B01)很大的一個改進就是加入了對dtrace探測點的支援了, 具體參見這裡, 主要目標是方便在生產實踐中定位複雜的效能問題。 目前Erlang的虛擬機器的探測點支援Linux的systemtap和freebsd的dtrace,我們剛好能夠享受的到。 作者Scot

系統技術業餘研究 » Erlang 網路密集型伺服器的瓶頸解決思路

最近我們的Erlang IO密集型的伺服器程式要做細緻的效能提升,從每秒40萬包處理提升到60萬目標,需要對程序和IO排程器的原理很熟悉,並且對行為進行微調,花了不少時間參閱了相關的文件和程式碼。 其中最有價值的二篇文章是: 1. Characterizing the Scalability of

系統技術業餘研究 » gen_tcp:send的深度解刨使用指南(初稿)

在大家的印象中, gen_tcp:send是個很樸素的函式, 一呼叫資料就喀嚓喀嚓到了對端. 這是個很大的誤解, Erlang的otp文件寫的很不清楚. 而且這個功能對於大部分的網路程式是至關重要的, 它的使用對否極大了影響了應用的效能. 我聽到很多同學在抱怨erlang的效能低或者出了很奇怪的問

系統技術業餘研究 » 計算機各系統元件的吞吐量延遲 看圖不說話

這個圖挺好的,就是比較粗線條,有些東西不太完整/準確,比如現有的USB實際上是480M/12M和1.5M三種速率(暫不算3.0和無線的) 另:幫樓主補充一下這類資料的意義:如果對各種匯流排的速率和IOPS如果沒有概念和預估,寫程式時就只能Compile & Pray了。 Reply:O

系統技術業餘研究 » 如何在TILEPro64多核心板卡上編譯執行Erlang

美國Tilera公司的眾核伺服器,單顆核心包含64顆CPU。硬體架構圖: 卡長這樣的: Erlang已經可以在這款CPU上成功執行,我們可以參考Ulf Wiger在Multicore ☺ Message-passing Concurrency 文件中關於Erlang在Tilera上的效能圖

系統技術業餘研究 » Erlangport通訊的資料格式

erlang內建的port非常強大,是erlang通往外面世界的通道,所以port和erlang程式的通訊的資料格式影響了通訊的效率,和穩定性。我們在選擇格式的時候, 會優先考慮到erlang的特性和port程式編寫語言的特點,選出一種2者都容易處理的格式。 通訊通常有2種,基於行的文字和2進位制

系統技術業餘研究 » erlang的profile工具原理優缺點

erlang的tools application下包含了一系列的profile工具, 包括 eprof cprof fprof, 具體的使用可以參看文件和<< erlang effective guide>>. 我這裡要說的是他們的工作原理。 這些模組的核心都是根據erla

系統技術業餘研究 » 轉:CPU密集型計算 erlangC 大比拼

原文地址:http://pseudelia.wordpress.com/2009/08/23/erlang-native-code-benchmark/ Normalerweise compiliert Erlang Bytecode (heißt das so in Erlang?). Das

系統技術業餘研究 » 區域性性原理在計算機分散式系統中的應用課程PPT

這個課程最主要focus在資料的區域性性原理,從硬體到作業系統到應用程式這樣的順序過來的,對於我們提高核心系統軟體的效能非常有啟發意義. 課件下載點選這裡 修正:由於原連結已經不存在了,特地在這裡放了一份。 以下是教程的介紹: 課程簡介 ___________________________

系統技術業餘研究 » erlang高階原理應用PPT

公司培訓用的 湊合看吧 主要講erlang系統的特點,分佈叢集以及mnesia的使用, 從比較高的角度來看erlang, 讓你有了大體觀. Post Footer automatically generated by wp-posturl plugin for wordpress. No

系統技術業餘研究 » BufferedIODirectIO混用導致的髒頁回寫問題

今天曲山同學在線上問道: 我測試發現,如果cp一個檔案,然後direct io讀這個檔案,會消耗很長時間。 我猜測dio不能用page cache,而這個檔案cp以後都在cache裡面,要強制刷到磁碟,才能讀? 我cp這個檔案很大,超過256M 由於資料檔案預設是用bufferedio方式開啟的

系統技術業餘研究 » posix_fadvise清除快取的誤解改進措施

在典型的IO密集型的資料庫伺服器如MYSQL中,會涉及到大量的檔案讀寫,通常這些檔案都是通過buffer io來使用的,以便充分利用到Linux作業系統的page cache。 Buffer IO的特點是讀的時候,先檢查頁快取裡面是否有需要的資料,如果沒有就從裝置讀取,返回給使用者的同時,加到快取

系統技術業餘研究 » Fio壓測工具io佇列深度理解誤區

Fio 是個強大的IO壓力測試工具,我之前寫過不少fio的使用和實踐,參見 這裡。 隨著塊裝置的發展,特別是SSD盤的出現,裝置的並行度越來越高。利用好這些裝置,有個訣竅就是提高裝置的iodepth, 一把餵給裝置更多的IO請求,讓電梯演算法和裝置有機會來安排合併以及內部並行處理,提高總體效率。