天天看點

高一緻分布式資料庫Galera Cluster

作者:王竹峰,去哪兒網資料庫專家,負責MySQL資料庫運維及相關開發工作。畢業于華中科技大學資料庫研究所,資深MySQL資料庫專家,一直緻力于MySQL資料庫源碼的研究與探索,擅長資料庫的開發、管理和維護。

本文為《程式員》原創文章,未經允許不得轉載,更多精彩文章請訂閱2017年《程式員》

糾錯、尋求報道或者投稿歡迎緻郵:[email protected]。

何謂Galera Cluster?就是內建了Galera插件的MySQL叢集,是一種新型的,資料不共享的,高度備援的高可用方案,目前Galera Cluster有兩個版本,分别是Percona Xtradb Cluster和MariaDB Cluster,都基于Galera,是以這裡都統稱為Galera Cluster,因為Galera本身具有多主特性,是以Galera Cluster也就是Multi-Master的叢集架構,如圖1所示。

高一緻分布式資料庫Galera Cluster

圖 1

圖1中有三個執行個體,組成了一個叢集,而這三個節點與普通主從架構不同,都可作為主節點,三個節點對等,這種一般稱為Multi-Master架構,當有用戶端要寫入或讀取資料時,随便連接配接哪個執行個體都一樣,讀到的資料相同,寫入某一節點後,叢集自己會将新資料同步到其他節點上,這種架構不共享任何資料,是一種高備援架構。

一般使用方法是,在這個叢集上再搭建一個中間層,這個中間層的功能包括建立連接配接,管理連接配接池,負責使三個執行個體的負載基本平衡,負責在用戶端與執行個體的連接配接斷開之後重連,也可以負責讀寫分離(在機器性能不同的情況下可以做這樣的優化)等,使用這個中間層後,由于這三個執行個體的架構在用戶端方面是透明的,用戶端隻需要指定這個叢集的資料源位址,連接配接到中間層即可,中間層會負責用戶端與伺服器執行個體連接配接的傳遞工作,由于這個架構支援多點寫入,是以完全避免了主從複制經常出現的資料不一緻問題,進而可以做到高度優雅的主從讀寫切換,在不影響使用者的情況下,進行離線維護等工作,MySQL的高可用從此開始,非常完美。

這裡最核心的問題其實是:在三個執行個體之間,因為它們關系對等,那麼在同時寫入時,如何保證整個叢集資料的一緻、完整與正确?

通常在使用MySQL的過程中,也不難實作一種Multi-Master架構,但是一般需要上層應用來配合,比如先要約定每個表必須有自增列,并且如果是2個節點的情況,一個節點隻能寫偶數值,而另一個節點隻能寫奇數值,同時2個節點之間互相做複制,因為2個節點寫入的東西不同,是以複制不會沖突,在這種約定之下,可以基本實作多Master架構,也可以保證資料的完整性與一緻性。但這種方式使用起來還是有限制,同時還會出現複制延遲,且不具有擴充性,不是真正意義上的叢集。

Galera的引入

現在已經知道,Galera Cluster是MySQL封裝了具有高一緻性,支援多點寫入的同步通信子產品Galera而做的,它建立在MySQL同步基礎之上;使用Galera Cluster時,應用程式可以直接讀、寫某個節點的最新資料,并且可以在不影響應用程式讀寫的情況下,下線某個節點;因為支援多點寫入,使得Failover變得非常簡單。

所有的Galera Cluster,都對Galera所提供的接口API做了封裝,這些API為上層提供了豐富的狀态資訊及回調函數,通過這些回調函數,做到了真正的多主叢集、多點寫入和同步複制,這些API被稱作Write-Set Replication API,簡稱wsrep API。

通過這些API,Galera Cluster提供了基于驗證的複制,是一種樂觀的同步複制機制,一個将要被複制的事務(稱為寫集),不僅包括被修改的資料庫行,還包括這個事務産生的所有Binlog,每一個節點在複制事務時,都會拿這些寫集與正在APPLY隊列的寫集做比對,如果沒有沖突,這個事務就可以繼續送出,或APPLY,此時就認為這個事務被送出了,然後在資料庫層面,還需要繼續做事務上的送出操作。

這種方式的複制,也被稱為是虛拟同步複制,實際上是一種邏輯上的同步,因為每個節點的寫入和送出操作還是獨立的,更準确的說是異步的。Galera Cluster建立在一種樂觀複制的基礎上,假設叢集中的每個節點都同步,加上在寫入時都會做驗證,那麼理論上是不會出現不一緻的,當然也不能這麼樂觀,如果出現不一緻,比如主庫(相對)插入成功,而從庫則出現主鍵沖突,那說明此時資料庫已經不一緻,這種情況下Galera Cluster采取的方式是将出現不一緻資料的節點踢出叢集,其實是自己shutdown了。

而通過使用Galera,它在其中通過判斷鍵值的沖突方式實作了真正意義上的Multi-Master,Galera Cluster在MySQL生态中,在高可用方面實作了非常重要的提升,目前Galera Cluster具備的功能包括以下幾個方面:

  1. 多主架構:真正的多點讀寫叢集,在任何時候讀寫資料,都是最新的。
  2. 同步複制:叢集不同節點之間資料同步,沒有延遲,在資料庫挂掉後,資料不會丢失。
  3. 并發複制:從節點APPLY資料時,支援并行執行,有更好的性能表現。
  4. 故障切換:在出現資料庫故障時,因為支援多點寫入,切換非常容易。
  5. 熱插拔:在服務期間,如果資料庫挂了,隻要監控程式發現得夠快,不可服務時間就會非常少。在節點故障期間,節點本身對叢集的影響非常小。
  6. 自動節點克隆:在新增節點,或停機維護時,增量資料或者基礎資料不需要人工手動備份提供,Galera Cluster會自動拉取線上節點資料,最終叢集會變為一緻。
  7. 對應用透明:叢集的維護對應用程式是透明的,幾乎感覺不到。

以上幾點,足以說明Galera Cluster是一個既穩健,又在資料一緻性、完整性和高性能方面有出色表現的高可用解決方案。

目前熟知的一些特性,或者在運維中需要注意的一些特性,有以下幾個方面:

Galera Cluster寫集内容

Galera Cluster複制的方式,仍基于Binlog,很多人也一直為此困擾,因為目前Percona Xtradb Cluster所實作的版本中,将Binlog關掉後,還可以使用,這誤導了很多人,其實關掉之後,隻是不落地了,表象上看上去沒有使用Binlog,實際上内部還是悄悄打開了。除此之外,寫集中還包括事務影響的所有行的主鍵,所有主鍵組成了寫集的KEY,而Binlog組成了寫集的DATA,這樣一個KEY-DATA就是寫集。

KEY和DATA分别具有不同的作用,KEY用來驗證與其它事務沒有沖突,而DATA則在驗證通過後做APPLY。

Galera Cluster的并發控制

從前文可以得知,Galera Cluster可以實作叢集中資料的高度一緻性,并且在每個節點上生成的Binlog順序都一樣,這與Galera内部實作的并發控制機制是分不開的。所有的上層到下層的同步、複制、執行、送出都通過并發控制機制來管理。這樣才能保證上層的邏輯性,下層資料的完整性等。

高一緻分布式資料庫Galera Cluster

圖 2

圖2截取自官方手冊,從圖中可以大概看出,從事務執行開始,到本地執行,再到寫集發送,再到寫集驗證,再到寫集送出的整個過程,以及從節點(相對)收到寫集後,所做的寫集驗證、寫集APPLY和寫集送出操作,通過對比該圖,可以很好地了解每一個階段的意義及性能等,下面就每一個階段以及其并發控制行為做一個簡單介紹:

  • 本地執行

這個階段,是事務執行的最初階段,可以說,這個階段的執行過程,與單點MySQL執行沒什麼差別,并發控制當然就是資料庫的并發控制,而不是Galera Cluster的并發控制。

  • 寫集發送

執行完之後,就到了送出階段,送出之前首先将産生的寫集廣播出去,而為了保證全局資料的一緻性,在寫集發送時,需要串行,這就屬于Galera Cluster并發控制的一部分。

  • 寫集驗證

這個階段,就是我們通常說的Galera Cluster的驗證,驗證是将目前事務與本地寫集驗證緩存集做驗證,通過比對寫集中被影響的資料庫KEYS,來發現有沒有相同的,來确定是不是可以驗證通過,那麼這個過程,也是串行的。

  • 寫集送出

這個階段,是一個事務執行的最後一個階段,驗證完成後,就可以進入送出階段,因為此時已經執行完,而送出操作的并發控制可以通過參數來控制其行為,即參repl.commit_order,如果設定為3,表示送出就是串行的,而這也是本人所推薦的(預設值)一種設定,因為這樣的結果是,叢集中不同節點産生的Binlog完全一樣,運維中帶來了不少好處和友善。

  • 寫集APPLY

這個階段,與上面的幾個在流程上不太一樣,這個階段是從節點做的事情,從節點隻包括兩個階段,即寫集驗證和寫集APPLY,寫集APPLY的并發控制與參數wsrep_slave_threads有關,本身在驗證之後,确定互相的依賴關系,如果确定沒有關系,就可以并行,而并行度就是參數wsrep_slave_threads的事情了。wsrep_slave_threads可以參照參數wsrep_cert_deps_distance來設定。

流量控制

在PXC中,有一個參數叫fc_limit,它的作用是什麼呢?如果一套叢集中,某個節點,或者某幾個節點的硬體資源較差,或由于節點壓力大,導緻複制效率低下等各種原因,其結果是:從節點APPLY時,速度非常慢,也就是說,主庫在1秒鐘之内做的操作,從庫有可能會用2秒才能完成,那麼這種情況下,就會導緻從節點執行任務的堆積,接收隊列的堆積。

假設從節點真的堆積了,那麼Galera會讓它一直堆積下去嗎?這樣延遲會越來越嚴重,Galera Cluster将變成一個主從架構的叢集,已經失去了強一緻狀态的屬性,那麼很明顯,Galera是不會讓這種事情發生的。此時就說回到開頭提到的參數gcs.fc_limit,這個參數在MySQL參數wsrep_provider_options中配置,是Galera的一個參數集合。有關于Flow Control的,還包括gcs.fc_factor,這兩個參數的意義是,當從節點堆積的事務數量超過gcs.fc_limit的值時,從節點發起一個Flow Control,而當從節點堆積的事務數小于gcs.fc_limit * gcs.fc_factor時,發起Flow Control的從節點再發起一個解除的消息,讓整個叢集再恢複。

但我們關心的是如何解決,下面有幾個一般所采用的方法:

  1. 發送FC消息的節點,硬體有可能出現了問題,比如I/O寫不進去,很慢,CPU異常高等。
  2. 發送FC消息的節點,本身資料庫壓力太高,比如目前節點承載太多的讀,導緻機器Load高,I/O壓力大等。
  3. 發送FC消息的節點,硬體壓力都沒有太大問題,但做得比較慢,一般原因是主庫并發高,但從節點的并發跟不上主庫,那麼此時可能需要觀察這兩個節點的并發度大小,可以參考狀态參數wsrep_cert_deps_distance的值,來調整從節點的wsrep_slave_threads,此時應該可以解決或緩解,這個問題可以這樣去了解,假設叢集每個節點的硬體資源都相當,那麼主庫可以執行完,從庫為什麼做不過來?那麼一般思路就是像處理主從複制的延遲問題一樣。
  4. 檢查存不存在沒有主鍵的表,因為Galera的複制是行模式的,是以如果存在這樣的表,主節點通過語句來修改,比如一個更新語句,更新了全表。而從節點收到之後,就會針對每一行的Binlog做一次全表掃描,這樣導緻這個事務在從節點執行,比在主節點執行慢十倍,或者百倍,進而導緻從節點堆積進而産生FC。

有很多坑?

有很多同學,在使用過Galera Cluster之後,發現很多問題,最大的比如DDL執行、大事務等,導緻服務不友好,這也是很多人放棄的原因。

  1. DDL執行卡死傳說:在Galera Cluster中執行一個大的改表操作,會導緻整個叢集在一段時間内完全寫入不了任何事務,都卡死在那裡。這個情況确實很嚴重,導緻線上完全不可服務,原因還是并發控制,因為送出操作設定為串行,DDL執行是一個送出過程,那麼串行執行改表,當然執行多久,就卡多久,直到改表執行完,其它事務也就可以繼續操作了。這個問題現在沒辦法解決,但我們長期使用下來發現,小表可以這樣直接操作,大一點或者更大的,都是通過OSC(pt-online-schema-change)來做。
  2. 擋我者死:由于Galera Cluster在執行DDL時,是Total Ordered Isolation(wsrep_OSU_method=TOI)的,是以必須要保證每個節點都同時執行,當然對于不是DDL的,也是Total Order的,因為每一個事務都具有同一個GTID值,DDL也不例外。而DDL涉及到的是表鎖,MDL鎖(Meta Data Lock),隻要在執行過程中,遇到了MDL鎖的沖突,所有情況下,都是DDL優先,将所有使用到這個對象的事務,統統殺死。不管是讀事務,還是寫事務,被殺的事務都會報出死鎖異常。不過這點現在确實沒有辦法解決,也無法避免,不過其影響尚能接受,可以先忍忍。
  3. 不死之身:繼上面的“擋我者死”,如果叢集真的被一個DDL卡死了,導緻整個叢集都動不了,所有的寫請求都Hang住了,那麼可能會有人想一個妙招——趕緊殺死,直接在每個節點上面輸入kill connection_id等類似的操作,那麼将報出很不願意看到的資訊:You are not owner of thread connection_id。此時可能有些同學要哭了,不過這種情況下,确實沒有什麼好的解決方法(其實這個時候,一個故障已經發生,一年的KPI也許已經沒有了,就看是否敢下狠手),其一是等DDL執行完成(所有這個資料庫上面的業務都處于不可服務狀态),否則就将資料庫直接Kill掉,快速重新開機,趕緊恢複一個節點送出線上服務,然後再考慮叢集其它節點資料增量的同步等,這也是Galera Cluster中最大的一個坑,需要非常小心。
SDCC 2017·上海站将于2017年3月17-19日登陸申城,三大技術峰會和24位嘉賓,彙聚國内知名的網際網路公司CTO、架構師、技術總監,暢談運維、資料庫和架構的熱門話題和技術熱點,遇見精益運維發起人&優維科技CEO王津銀、MongoDB大中華區首席架構師唐建法和華為軟體API開放平台架構師李林鋒等大牛。截止3月5日前門票八折優惠中,5人以上團購立減400元,詳情點選注冊參會。