MYSQL(高可用方案)

本次專題是 MySQL高可用方案選型,這個專題想必有很多同學感興趣。

高可用的意義以及各種不同高可用等級相應的停機時間我就不必多說了,直接進入主題。

可選MySQL高可用方案

MySQL的各種高可用方案,大多是基於以下幾種基礎來部署的:

  1. 基於主從複製;

  2. 基於Galera協議;

  3. 基於NDB引擎;

  4. 基於中間件/proxy;

  5. 基於共享存儲;

  6. 基於主機高可用;

在這些可選項中,最常見的就是基於主從複製的方案,其次是基於Galera的方案,我們重點說說這兩種方案。其餘幾種方案在生產上用的並不多,我們只簡單說下。

基於主從複製的高可用方案

雙節點主從 + keepalived/heartbeat

一般來說,中小型規模的時候,採用這種架構是最省事的。
兩個節點可以採用簡單的一主一從模式,或者雙主模式,並且放置於同一個VLAN中,在master節點發生故障後,利用keepalived/heartbeat的高可用機制實現快速切換到slave節點。

在這個方案裏,有幾個需要注意的地方:

  • 採用keepalived作爲高可用方案時,兩個節點最好都設置成BACKUP模式,避免因爲意外情況下(比如腦裂)相互搶佔導致往兩個節點寫入相同數據而引發衝突;

  • 把兩個節點的auto_increment_increment(自增起始值)和auto_increment_offset(自增步長)設成不同值。其目的是爲了避免master節點意外宕機時,可能會有部分binlog未能及時複製到slave上被應用,從而會導致slave新寫入數據的自增值和原先master上衝突了,因此一開始就使其錯開;當然了,如果有合適的容錯機制能解決主從自增ID衝突的話,也可以不這麼做;

  • slave節點服務器配置不要太差,否則更容易導致複製延遲。作爲熱備節點的slave服務器,硬件配置不能低於master節點;

  • 如果對延遲問題很敏感的話,可考慮使用MariaDB分支版本,或者直接上線MySQL 5.7最新版本,利用多線程複製的方式可以很大程度降低複製延遲;

  • 對複製延遲特別敏感的另一個備選方案,是採用semi sync replication(就是所謂的半同步複製)或者後面會提到的PXC方案,基本上無延遲,不過事務併發性能會有不小程度的損失,需要綜合評估再決定;

  • keepalived的檢測機制需要適當完善,不能僅僅只是檢查mysqld進程是否存活,或者MySQL服務端口是否可通,還應該進一步做數據寫入或者運算的探測,判斷響應時間,如果超過設定的閾值,就可以啓動切換機制;

  • keepalived最終確定進行切換時,還需要判斷slave的延遲程度。需要事先定好規則,以便決定在延遲情況下,採取直接切換或等待何種策略。直接切換可能因爲複製延遲有些數據無法查詢到而重複寫入;

  • keepalived或heartbeat自身都無法解決腦裂的問題,因此在進行服務異常判斷時,可以調整判斷腳本,通過對第三方節點補充檢測來決定是否進行切換,可降低腦裂問題產生的風險。

雙節點主從+keepalived/heartbeat方案架構示意圖見下:

MySQL雙節點高可用架構

圖解:MySQL雙節點(單向/雙向主從複製),採用keepalived實現高可用架構。

多節點主從+MHA/MMM

多節點主從,可以採用一主多從,或者雙主多從的模式。
這種模式下,可以採用MHA或MMM來管理整個集羣,目前MHA應用的最多,優先推薦MHA,最新的MHA也已支持MySQL 5.6的GTID模式了,是個好消息。
MHA的優勢很明顯:

  • 開源,用Perl開發,代碼結構清晰,二次開發容易;

  • 方案成熟,故障切換時,MHA會做到較嚴格的判斷,儘量減少數據丟失,保證數據一致性;

  • 提供一個通用框架,可根據自己的情況做自定義開發,尤其是判斷和切換操作步驟;

  • 支持binlog server,可提高binlog傳送效率,進一步減少數據丟失風險。

不過MHA也有些限制

  • 需要在各個節點間打通ssh信任,這對某些公司安全制度來說是個挑戰,因爲如果某個節點被黑客攻破的話,其他節點也會跟着遭殃;

  • 自帶提供的腳本還需要進一步補充完善,當然了,一般的使用還是夠用的。

多節點主從+etcd/zookeeper

在大規模節點環境下,採用keepalived或者MHA作爲MySQL的高可用管理還是有些複雜或麻煩。
首先,這麼多節點如果沒有采用配置服務來管理,必然雜亂無章,線上切換時很容易誤操作。
在較大規模環境下,建議採用etcd/zookeeper管理集羣,可實現快速檢測切換,以及便捷的節點管理。

基於Galera協議的高可用方案

Galera是Codership提供的多主數據同步複製機制,可以實現多個節點間的數據同步複製以及讀寫,並且可保障數據庫的服務高可用及數據一致性。
基於Galera的高可用方案主要有MariaDB Galera Cluster和Percona XtraDB Cluster(簡稱PXC),目前PXC用的會比較多一些。

PXC的架構示意圖見下:

pxc overview

(圖片源自網絡),圖解:在底層採用wsrep接口實現數據在多節點間的同步複製。

 

pxc certification

(圖片源自網絡),圖解:在PXC中,一次數據寫入在各個節點間的驗證/回滾流程。

PXC的優點

  • 服務高可用;

  • 數據同步複製(併發複製),幾乎無延遲;

  • 多個可同時讀寫節點,可實現寫擴展,不過最好事先進行分庫分表,讓各個節點分別寫不同的表或者庫,避免讓galera解決數據衝突;

  • 新節點可以自動部署,部署操作簡單;

  • 數據嚴格一致性,尤其適合電商類應用;

  • 完全兼容MySQL;

雖然有這麼多好處,但也有些侷限性:

  • 只支持InnoDB引擎;

  • 所有表都要有主鍵;

  • 不支持LOCK TABLE等顯式鎖操作;

  • 鎖衝突、死鎖問題相對更多;

  • 不支持XA;

  • 集羣吞吐量/性能取決於短板;

  • 新加入節點採用SST時代價高;

  • 存在寫擴大問題;

  • 如果併發事務量很大的話,建議採用InfiniBand網絡,降低網絡延遲;

事實上,採用PXC的主要目的是解決數據的一致性問題,高可用是順帶實現的。因爲PXC存在寫擴大以及短板效應,併發效率會有較大損失,類似semi sync replication機制。

其他高可用方案

  • 基於NDB Cluster,由於NDB目前仍有不少缺陷和限制,不建議在生產環境上使用;

  • 基於共享存儲,一方面需要不太差的存儲設備,另外共享存儲可也會成爲新的單點,除非採用基於高速網絡的分佈式存儲,類似RDS的應用場景,架構方案就更復雜了,成本也可能更高;

  • 基於中間件(Proxy),現在可靠的Proxy選擇並不多,而且沒有通用的Proxy,都有有所針對,比如有的專注解決讀寫分離,有的專注分庫分表等等,真正好用的Proxy一般要自行開發;

  • 基於主機高可用,是指採用類似RHCS構建一個高可用集羣后,再部署MySQL應用的方案。老實說,我沒實際用過,但從側面瞭解到這種方案生產上用的並不多,可能也有些侷限性所致吧;

以DBA們的聰明才智,肯定還有其他我不知道的方案,也歡迎同行們間多多交流。

 

 

從 MySQL+MMM 到 MariaDB+Galera Cluster : 一個高可用性系統改造

很少有事情比推出高可用性(HA)系統之後便經常看到的系統崩潰更糟糕。對於我們這個Rails運行機的團隊來說,這個失效的HA系統是MySQL多主複製管理器(MMM)

25081034_gj7s.png

我們已經找尋MMM的替代品有一段時間了,幾個月之前,我們轉換到了MariaDB + Galera Cluster以尋求高可用的Mysql。

MMM怎麼了,Galera Cluster又有什麼特別之處呢?繼續閱讀!

MySQL多主機複製 (MMM)基本被打破

MySQL MMM 是如何工作的:一臺安裝了MySQL MMM的服務器每十秒種(默認間隔)輪詢一次MySQL節點, 來檢查其狀態。僅其中的一臺服務器接收到寫入器角色 - 其他的可以擁有閱讀器角色。 MMM 維護了一個虛擬IP,這個IP指向擁有寫入器角色的節點。

問題在於輪詢:如果MySQL每十分鐘輪詢,那麼如果寫入器節點在檢查的間歇出現故障怎麼辦?如果你設置了HA你可能正處理着許多事務 - 在MMM檢測到寫入器節點不正常之前,可能已經有成千上萬的事務失敗了。更糟糕的是,如果存在一種內部問題:複製失敗在先,事務失敗在後,那麼你要把寫入器角色轉到其他節點上嗎?但是其他節點不一定符合原始的寫入器節點。

減少輪詢間隔到1秒也不能修正這個問題-大型數據庫可能在每秒內運行許多事務。

因此輪詢是根本問題,而且超出了根本問題範圍。無法控制的MySQL MMM經常產生難以恢復的問題。Baron Swartz在Percona的MySQL大神上對MMM的缺陷有如下描述:

簡要地來說,MMM產生的宕機時間比它要防止的宕機時間更長。因此它是一個低可靠性的工具,不是高可靠性的工具。它可以讓你連續幾天以7X24小時的工作方式從宕機的機器裏提取數據,並放回到服務器上,這隻會導致系統真正的非常嚴重的一塌糊塗。因此,MMM賦予詞語"cluset-f__k"新的意義。

儘管MMM存在缺陷,然而它至少是對MySQL進行高可靠性的一次突破。然而時間改變了一切。甚至MySQL MMM的創建者也說到了要更改的時候了。Baron有關MMM的博客日誌有Alexey's的如下評論:

我是MMM的最初的作者,我完全同意你的意見。每次我試圖給集羣添加HA的時候,我都會想起MMM,而且需要親自去嘗試,因爲我只是不確定這個工具的我所做的配置。而且市場上沒有其他軟件可以可靠地做這項工作。

那麼,爲什麼Galera是最好的MySQL HA解決方案呢?

我們的Galera Cluster設置仍然使用輪詢來做健康檢測——這比MMM好在哪裏呢?

答案在於主從複製怎樣是運作的。對於標準版的MySQL,對master的寫操作被記錄於一個二進制的日誌。Slave會在之後複製二進制日誌中的查詢。查詢在寫服務器上運行與在其它節點上運行時刻之間,總是會有一個延遲。它是異步的

MySQL異步複製有下面的問題:

  • slave服務器的數據集總是落後於master服務器。

  • MySQL複製很慢——它從二進制日誌回訪事務。

對於Galera,事務是在它們被提交之前被所有節點確認。如果一個事務在一個節點失敗了,那個節點將立刻從羣集中移除。換句話說,Galera主從複製是同步的。你 永遠也不會丟失事務——沒有延遲 (而且Galera的 基於行的複製大約要快5倍速)。

Galera集羣是局內人

MySQL MMM 是一個局外者—— 對於服務器上實際在發生的事情它是“啞的”。它只做一種檢測,而且那就是它所知道的全部該如何反應的事情。

Galera集羣是一個“局內人”,因此對每個節點的內部狀態要更機靈,並且不需要人工干預就可以做正確的事情(例如,一個節點同步或未同步,成爲一個donor(節點處於爲新節點準備或傳輸集羣全量數據狀態,對客戶端不可用),等等——全部都是自動的)。

當寫入節點失敗的時候會發生什麼呢?

由於用一個Galera集羣可以寫進任意節點,我們還是選擇儘量減少潛在的死鎖和只在一個節點寫入。爲此,我們使用HAProxy:我們擁有一個前端供“寫入者”節點,另一個前端供讀出以供所有節點實現餘額查詢。“寫入者”通過單個節點發送請求,而其他的節點作爲備份。

如果HAProxy檢測到“寫入者”節點不正常,它立即提拔備份節點中的一個作爲“寫入者”。MySQL的MMM在這種情況下通常會關掉所有節點之間的通話——HAProxy不會如此。當“寫入者”後臺更新的時候,我們可能會丟失一部分請求,但它不會導致不一致的數據集通過服務器,這比癱瘓更糟糕。

我們不會自動修復失敗的節點,不過這沒有關係。我主要關注點是確保一個正常的節點在執行寫入,HAProxy是做這個的。

修復失效的節點(並讓它作爲一個新的節點處於在線狀態)

當一個節點在標準的MySQL複製的時候失效,你將在再次進行復制的時候把大量的負載集中在一臺服務器上(這臺服務器不僅僅要進行讀和寫,而且還要承接來自innodbbackupex的負載)。

使用Galera,你可以讓其中一個節點離線(因此你至少需要三個節點)。這時這個節點就成爲供給者節點-對它的寫操作將被阻塞。這個節點就通過rsync傳輸自身的數據給失效的節點(或者新的節點)。然後,供給者節點和失效節點通過輔助隊列運行查詢而與其他節點保持同步。

一旦這兩個節點回歸到同步狀態,HAProxy將自動的標記它們爲啓動狀態,然後把它們添回道前端。

Galera集羣也支持普通的MySQL,因此我們爲什麼不切換到MariaDB?

切換到MariaDB的理由既有技術原因也有政治原因:

  • 易於移植:首先,MariaDB是MySQL的隨手可得的替代品。從MySQL 5.1移植到MariaDB,只有Galera服務器5.6可以運行。

  • 性能:我們有幾個包含索引的在性能方面存在問題的查詢,後面通過令人驚訝的移植來”修補“這方面的問題。MariaDB似乎更適合於複雜查詢和連接,而Rails上的Ruby也因處理複雜的查詢和連接而揚名。MariaDB更適合做查找索引的整個工作,而且正如我前面所說,許多令人煩惱的查詢現在已經提速了。我們似乎看不到二者在內存使用上有任何令人吃驚的區別。我期望Galera能更多的使用內存,不過如果這麼做了,那麼Galera就沒有任何值得關注的地方了。

  • 社團:MariaDB有很大的驅動力,而且與MySQL相比增加了更多的功能。Oracle對MySQL未來傾注了大量的心血,而MariaDB看起來也存活了好長時間-甚至谷歌正在切換到MariaDB

我們會再做一次?

絕對地。我們沒有看到有什麼原因不切換到 MariaDB 和 Galera Cluster。

監控 Galera Cluster

25081035_S1or.png

監控 Galera 的一件偉大的事情是它是分層的 - 我們可以很容易地監視棧的每一部分。我們使用 Scout 來監視,那意味着我們僅僅需要去使用下列插件:

  • MariaDB Galera Cluster - 安裝在每一個 Galera Cluster 結點上去獲取關鍵指標(本地狀態,連通性,等)。

  • HAProxy - 爲每一個代理安裝(寫入器一次,讀取器一次)。

  • URL Monitoring - 檢測和 HAProxy 檢測的相同的狀態URL來決定結點的健康。

TL;DR

直到最近, MySQL MMM 是添加高可用性到 MySQL 的最好的(但壞了的)途徑。Galera Cluster 最終爲 MySQL 增加了真實的高可用性,主要多虧同步複製。

 

MariaDB作爲Mysql的一個分支,在開源項目中已經廣泛使用,例如大熱的openstack,所以,爲了保證服務的高可用性,同時提高系統的負載能力,集羣部署是必不可少的。

MariaDB Galera Cluster 介紹

MariaDB集羣是MariaDB同步多主機集羣。它僅支持XtraDB/ InnoDB存儲引擎(雖然有對MyISAM實驗支持 - 看wsrep_replicate_myisam系統變量)。

主要功能:

  • 同步複製

  • 真正的multi-master,即所有節點可以同時讀寫數據庫

  • 自動的節點成員控制,失效節點自動被清除

  • 新節點加入數據自動複製

  • 真正的並行複製,行級

  • 用戶可以直接連接集羣,使用感受上與MySQL完全一致

優勢:

  • 因爲是多主,所以不存在Slavelag(延遲)

  • 不存在丟失事務的情況

  • 同時具有讀和寫的擴展能力

  • 更小的客戶端延遲

  • 節點間數據是同步的,而Master/Slave模式是異步的,不同slave上的binlog可能是不同的

技術:

Galera集羣的複製功能基於Galeralibrary實現,爲了讓MySQL與Galera library通訊,特別針對MySQL開發了wsrep API。

Galera插件保證集羣同步數據,保持數據的一致性,靠的就是可認證的複製,工作原理如下圖: 

當客戶端發出一個commit的指令,在事務被提交之前,所有對數據庫的更改都會被 write-set 收集起來,並且將write-set 紀錄的內容發送給其他節點。

write-set 將在每個節點進行認證測試,測試結果決定着節點是否應用write-set更改數據。

如果認證測試失敗,節點將丟棄 write-set ;如果認證測試成功,則事務提交。

1 安裝環境準備

安裝MariaDB集羣至少需要3臺服務器(如果只有兩臺的話需要特殊配置,請參照官方文檔

在這裏,我列出試驗機器的配置:

操作系統版本:centos7

node4:10.128.20.16 node5:10.128.20.17 node6:10.128.20.18

以第一行爲例,node4爲 hostname ,10.128.20.16爲 ip ,在三臺機器修改 /etc/hosts 文件,我的文件如下:

10.128.20.16 node4
10.128.20.17 node5
10.128.20.18 node6

爲了保證節點間相互通信,需要禁用防火牆設置(如果需要防火牆,則參照官方網站增加防火牆信息設置)

在三個節點分別執行命令:

systemctl stop firewalld

然後將 /etc/sysconfig/selinux 的 selinux 設置成 disabled ,這樣初始化環境就完成了。

2 安裝 MariaDB Galera Cluster

[root@node4 ~]# yum install -y mariadb mariadb-galera-server mariadb-galera-common galera rsync
[root@node5 ~]# yum install -y mariadb mariadb-galera-server mariadb-galera-common galera rsync
[root@node6 ~]# yum install -y mariadb mariadb-galera-server mariadb-galera-common galera rsync

3 配置 MariaDB Galera Cluster

初始化數據庫服務,只在一個節點進行

[root@node4 mariadb]# systemctl start mariadb
[root@node4 mariadb]# mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user.  If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none):
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.

Set root password? [Y/n]
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
 ... Success!


By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] n
 ... skipping.

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] y
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] n
 ... skipping.

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!

關閉數據庫,修改 /etc/my.cnf.d/galera.cnf

[root@node4 mariadb]# systemctl stop mariadb
[root@node4 ~]# vim /etc/my.cnf.d/galera.cnf

修改以下內容:

[mysqld]
......
wsrep_provider = /usr/lib64/galera/libgalera_smm.so
wsrep_cluster_address = "gcomm://node4,node5,node6"
wsrep_node_name = node4
wsrep_node_address=10.128.20.16
#wsrep_provider_options="socket.ssl_key=/etc/pki/galera/galera.key; socket.ssl_cert=/etc/pki/galera/galera.crt;"

提示:如果不用ssl的方式認證的話,請把 wsrep_provider_options 註釋掉。

將此文件複製到node5、node6,注意要把 wsrep_node_name 和 wsrep_node_address 改成相應節點的 hostname 和ip。

4 啓動 MariaDB Galera Cluster 服務

[root@node4 ~]# /usr/libexec/mysqld --wsrep-new-cluster --user=root &

觀察日誌:

[root@node4 ~]# tail -f /var/log/mariadb/mariadb.log

150701 19:54:17 [Note] WSREP: wsrep_load(): loading provider library 'none'
150701 19:54:17 [Note] /usr/libexec/mysqld: ready for connections.
Version: '5.5.40-MariaDB-wsrep'  socket: '/var/lib/mysql/mysql.sock'  port: 3306  MariaDB Server, wsrep_25.11.r4026

出現 ready for connections ,證明我們啓動成功,繼續啓動其他節點:

[root@node5 ~]# systemctl start mariadb
[root@node6 ~]# systemctl start mariadb

可以查看 /var/log/mariadb/mariadb.log,在日誌可以看到節點均加入了集羣中。

警告:--wsrep-new-cluster 這個參數只能在初始化集羣使用,且只能在一個節點使用。

5 查看集羣狀態

我們可以關注幾個關鍵的參數:

wsrep_connected = on 鏈接已開啓

wsrep_local_index = 1 在集羣中的索引值

wsrep_cluster_size =3 集羣中節點的數量

wsrep_incoming_addresses = 10.128.20.17:3306,10.128.20.16:3306,10.128.20.18:3306 集羣中節點的訪問地址

6 驗證數據同步

我們在 node4 上新建數據庫 galera_test ,然後在 node5 和 node6 上查詢,如果可以查詢到 galera_test 這個庫,說明數據同步成功,集羣運行正常。

[root@node4 ~]# mysql  -uroot  -proot  -e  "create database galera_test"
[root@node5 ~]# mysql  -uroot  -proot  -e  "show databases"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| galera_test        |
| mysql              |
| performance_schema |
+--------------------+
[root@node6 ~]# mysql  -uroot  -proot  -e  "show databases"
+--------------------+
| Database           |
+--------------------+
| information_schema |
| galera_test        |
| mysql              |
| performance_schema |
+--------------------+

至此,我們的 MariaDB Galera Cluster 已經成功部署。

 

https://www.cnblogs.com/robbinluobo/p/8294782.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章