理解 OpenStack 高可用(HA) (6): MySQL HA
本系列會分析OpenStack 的高可用性(HA)概念和解決方案:
(1)OpenStack 高可用方案概述
(2)Neutron L3 Agent HA - VRRP (虛擬路由冗余協(xié)議)
(3)Neutron L3 Agent HA - DVR (分布式虛機路由器)
(4)Pacemaker 和 OpenStack Resource Agent (RA)
(5)RabbitMQ HA
(6)MySQL HA
?
1. MySQL HA 方案
1.1 各種方案概述
Mysql HA 方案有很多種,包括:
- mmm:?http://mysql-mmm.org/
- mha:?https://code.google.com/p/mysql-master-ha/
- heartbeat+brdb:?http://lin128.blog.51cto.com/407924/279411?http://www.centos.bz/2012/03/achieve-drbd-high-availability-with-heartbeat/
- cluster(使用ndb引擎):http://database.51cto.com/art/201008/218326.htm
- 雙master+keeplived:?http://database.51cto.com/art/201012/237204.htm,http://kb.cnblogs.com/page/83944/
- 雙master:?http://yunnick.iteye.com/blog/1845301
- Oracel Fabric 方案:http://www.csdn.net/article/2014-08-20/2821300
這些高可用方案,大多是基于以下幾種基礎來部署的:
從 SLA 的角度看:
- 要達到99.9%:使用MYSQL復制技術
- 要達到99.99%:使用MYSQL NDB 集群和虛擬化技術
- 要達到99.999%:使用shared-nothing架構的GEO-REPLICATION和NDB集群技術
這里?有個各種方案的比較:
在這些可選項中,最常見的就是基于主從復制的方案,其次是基于Galera的方案。這篇文章?分享MYSQL中的各種高可用技術?全面具體地分析了 Mysql 的各種容災方案。也可見 Mysql 容災的水很深。
1.2?MySQL Cluster(NDB Storage Engine)
MySQL Cluster 是 MySQL 官方也就是 Oracle 主推的一種提供去中心化集群(shared-nothing clustering)和 自動共享(auto-sharding)的MySQL 數(shù)據(jù)庫管理系統(tǒng)。它被設計來提供高可用(99.999%)、高吐吞吐量、低延遲和幾乎線性擴展的解決方案。它是基于 MySQL 的 NDB 或者?NDBCLUSTER 存儲引擎實現(xiàn)的。(引用自?https://en.wikipedia.org/wiki/MySQL_Cluster)
官網(wǎng):https://www.mysql.com/products/cluster/
版本:MySQL Cluster 有獨立于 MySQL 的版本(7.4版本使用 MySQL 5.6;7.3版本使用 MySQL 5.5)
價格:https://www.mysql.com/products/
這是?Choosing the right MySQL High Availability Solution – webinar replay?MySQL Cluster 和其它幾個主要HA方案的 SLA 比較:
(1)特征
(2)架構
- 1)Sql結點(SQL node--上圖對應為MySQLd):分布式數(shù)據(jù)庫。包括自身數(shù)據(jù)和查詢中心結點數(shù)據(jù).
- 2)數(shù)據(jù)結點(Data node -- ndbd):集群共享數(shù)據(jù)(內存中).
- 3)管理服務器(Management Server – ndb_mgmd):集群管理SQL node,Data node.
支持最多 48 個 data nodes;集群最多 255 個節(jié)點
2. MariaDB 和 Galera Cluster
MySQL 被 Oracle 收購后,基于需求以及對 Oracle 的擔心,出現(xiàn)了兩個主要的分支。它們都是免費開源的軟件。
2.1 MySQL 的兩個主要分支之一之 MariaDB
? ? MariaDB由MySQL的創(chuàng)始人麥克爾·維德紐斯主導開發(fā),他早前曾以10億美元的價格,將自己創(chuàng)建的公司MySQL AB賣給了SUN,此后,隨著SUN被甲骨文收購,MySQL的所有權也落入Oracle的手中。MariaDB名稱來自麥克爾·維德紐斯的女兒瑪麗亞(英語:Maria)的名字。
? ? MariaDB的目的是完全兼容MySQL,包括API和命令行,使之能輕松成為MySQL的代替品。在存儲引擎方面,10.0.9版起使用XtraDB(名稱代號為Aria)來代替MySQL的InnoDB。
? ? 版本方面,MariaDB直到5.5版本,均依照MySQL的版本。因此,使用MariaDB5.5的人會從MySQL 5.5中了解到MariaDB的所有功能。從2012年11月12日起發(fā)布的10.0.0版開始,不再依照MySQL的版號。10.0.x版以5.5版為基礎,加上移植自MySQL 5.6版的功能和自行開發(fā)的新功能。
? ? 相對于最新的MySQL5.6,MariaDB在性能、功能、管理、NoSQL擴展方面包含了更豐富的特性。比如微秒的支持、線程池、子查詢優(yōu)化、組提交、進度報告等。
? ? 官網(wǎng)地址:https://mariadb.org/
2.2 MySQL 的兩個主要分支之二之 Percona
? Percona Server就是這樣一款產(chǎn)品,由領先的MySQL咨詢公司Percona發(fā)布。Percona Server是一款獨立的數(shù)據(jù)庫產(chǎn)品,為用戶提供了換出其MySQL安裝并換入Percona Server產(chǎn)品的能力。通過這樣做,就可以利用XtraDB存儲引擎。Percona Server聲稱可以完全與MySQL兼容,因此從理論上講,您無需更改軟件中的任何代碼。這確實是一個很大的優(yōu)勢,適合在您尋找快速性能改進時控制質量。因此,采用Percona Server的一個很好的理由是,利用XtraDB引擎來盡可能地減少代碼更改。
? 更多的比較,可以參考網(wǎng)上的大量文章,比如?
- 超越MySQL:三個流行MySQL分支的對比
- MySQL分支的選擇:Percona還是MariaDB
- MariaDB or PerconaDB 你選哪種來替代 MySQL?
2.3 Galera Cluster
? Galera Cluster 是一套在innodb存儲引擎上面實現(xiàn)multi-master及數(shù)據(jù)實時同步的系統(tǒng)架構,業(yè)務層面無需做讀寫分離工作,數(shù)據(jù)庫讀寫壓力都能按照既定的規(guī)則分發(fā)到各個節(jié)點上去。在數(shù)據(jù)方面完全兼容 MariaDB 和 MySQL。
官網(wǎng):http://galeracluster.com/products/
使用案例:HP, OpenStack,KPN
特征:
2.4 MySQL Galera Cluster
2.4.1 MySQL Galera Cluster 的特點和局限
? Galera Cluster 可以同時支持 MySQL 和 MariaDB:
- 安裝 MySQL Galera Cluster:需要安裝帶 wsrep patch 的MySQL版本(比如?MySQL 5.5.29)和 Galera復制插件,詳細步驟請參考?MySQL多主復制-MySQL Galera安裝部署
- 安裝 MiraDB Galera Cluster:參考?OpenStack 在 RedHat 平臺上的 MariaDB HA 方案,以及?MariaDB Galera Cluster 部署。
? 為了支持MySQL,Galera Cluster 中使用了由 Coreship 提供的補丁 (https://launchpad.net/codership-mysql)。MySQL Galera 集群:
- 使用通用的?Wsrep replication 來替代 MySQL Cluster 中的 Replication
- 基本 Quorum的集群,最少三個節(jié)點,只能奇數(shù)個節(jié)點
- 使用偶數(shù)個節(jié)點時,可以使用一個 Galera Arbiter (garbd)
- 較高的死鎖可能性:在多主集群中,不支持對表加鎖和解鎖(LOCK/UNLOCK TABLES cannot be supported in multi-master setups)。因此,在兩個transaction 從不同的節(jié)點更新同一個 row 的時候,只有一個 transaction 會成功,對另外一個transaction,MySQL 會返回死鎖錯誤(Error: 1213 SQLSTATE: 40001 (ER_LOCK_DEADLOCK))。
- 部署:
(本節(jié)信息來自 http://www.slideshare.net/Severalnines/galera-cluster-for-mysql-vs-mysql-ndb-cluster-a-high-level-comparison-42724783)??
- MySQL Galera 集群有非常多的使用限制(來源):
MySQL 5.6 的同樣描述在?percona/debian-percona-xtradb-cluster-5.6
原因和概率:
-
- MySQL Galera 在本地節(jié)點上使用悲觀鎖(pessimistic locking)
- MySQL Galera 在其它節(jié)點上使用樂觀鎖(optimistic locking)
- 在大的負載壓力下的發(fā)生概率大概為 1/500
- 在正常的負載壓力下的發(fā)生概率大概為 1/10000
?2.4.2 NDB (MySQL Cluster 使用的引擎)和 MySQL Galera Cluster 的性能對比
?
2.4.3 一些 best practice
常規(guī)的推薦做法:
減少死鎖的一些推薦做法:
?
3. 使用?Pacemaker + DRBD + CoroSync 的?A/P 方案?
與 RabbitMQ HA 方案類似,OpenStack 官方推薦的 Mysql Active/Passive HA 方案也是?Pacemaker + DRBD + CoroSync。具體方案為:
- 配置 DRBD 用于 Mysql
- 配置 Mysql 的 var/lib/mysql 目錄位于 DRBD 設備上
- 選擇和配置一個 VIP,配置 Mysql 在該 IP 上監(jiān)聽
- 使用 Pacemaker 管理 Mysql 所有的資源,包括其 deamon
- 配置 OpenStack 服務使用基于 VIP 的 Mysql 連接
OpenStack 官方推薦的 Mysql HA A/P 方案?配置完成后的效果:
這個文檔?詳細闡述了具體的配置步驟。這個方案的問題是,drbd 容易出現(xiàn)腦裂;而且,兩個 mysql 節(jié)點只有一個能提供服務,存在資源浪費。
4. 使用 MySQL Galera 的多主方案
4.1 三節(jié)點方案
架構如下:
?
Galera 主要功能:
- 同步復制
- 真正的multi-master,即所有節(jié)點可以同時讀寫數(shù)據(jù)庫
- 自動的節(jié)點成員控制,失效節(jié)點自動被清除
- 新節(jié)點加入數(shù)據(jù)自動復制
- 真正的并行復制,行級
- 用戶可以直接連接集群,使用感受上與MySQL完全一致?
優(yōu)勢:
- 因為是多主,所以不存在延遲
- 不存在丟失交易的情況
- 同時具有讀和寫的擴展能力
- 更小的客戶端延遲
- 節(jié)點間數(shù)據(jù)是同步的,而Master/Slave模式是異步的,不同slave上的binlog可能是不同的?
局限:見 4.3.1 章節(jié)的詳細描述
另外,MySQL Galera Cluster 并不是適合所有需要復制的情形,你必須根據(jù)自己的需求來決定,比如,
- 如果你是數(shù)據(jù)一致性考慮的多,而且寫操作和更新的東西多,但寫入量不是很大,MySQL Galera Cluster就適合你。但是,這種方案中整個集群的寫入吞吐量是由最弱的節(jié)點限制,如果有一個節(jié)點變得緩慢,那么整個集群將是緩慢的。為了穩(wěn)定的高性能要求,所有的節(jié)點應使用統(tǒng)一的硬件,而且集群節(jié)點建議最少3個。
- 如果你是查詢的多,且讀寫分離也容易實現(xiàn),那就用 replication 好,簡單易用,用一個 master 保證數(shù)據(jù)的一致性,可以有多個slave用來讀去數(shù)據(jù),分擔負載,只要能解決好數(shù)據(jù)一致性和唯一性,replication就更適合你,畢竟 MySQL?Galera Cluster集群遵循“木桶”原理,如果寫的量很大,數(shù)據(jù)同步速度是由集群節(jié)點中IO最低的節(jié)點決定的,整體上,寫入的速度會比replication慢許多。
詳細配置過程可以參考 OpenStack HA Guide,?這個文章?和?MySQL Multi-master Replication With Galera。
4.2 兩節(jié)點 +?Galera Arbitrator?A/A HA 方案
?3.1 中的A/A 方案需要三個節(jié)點,因此成本比較高。本方案提供使用兩個節(jié)點情況下的 A/A 方案。相信信息可以參考?這篇文章。
該方案使用 Arbitrator 作為第三個節(jié)點來使用,它其實是一個守護進程。它有兩個作用:
4.3 OpenStack 使用 HAProxy + MySQL Galera Cluster 的問題
這篇文章中,作者對200個OpenStack用戶/運維人員做過一個關于數(shù)據(jù)庫使用的調查,結果是
- 1 人使用?PostgreSQL
- 10幾個人使用標準的 MYSQL master/slave replication 方案
- 其他人都是用 MySQL Gelera 集群
4.3.1 問題原理
? OpenStack 官方推薦的A/A HA 方案是使用?Galera 來做三節(jié)點HA(http://docs.openstack.org/ha-guide/controller-ha-galera.html)。這種模式下,Galera 提供多個 Mysql 節(jié)點之間的同步復制,使得多個 Mysql 節(jié)點同時對外提供服務,這時候往往需要使用負載均衡軟件比如 HAProxy 來提供一個 VIP 給各應用使用。但是,OpenStack 文檔回避了這種MySql集群的問題。
? 對于 2.4.1 部分描述的 MySQL Galera 的一些局限,如果在 OpenStack 環(huán)境中使用 HAProxy 做整個MySQL Galera 的 LB 的話,?因為該集群不支持跨節(jié)點對表加鎖,也就是說如果OpenStack 某組件有兩個會話分布在兩個節(jié)點上同時寫入某一條數(shù)據(jù),那么其中一個會話將會遇到死鎖的情況。網(wǎng)上這種情況的報告非常多,比如:
- https://bugzilla.redhat.com/show_bug.cgi?id=1141972?Cause: Unhandled database deadlock conditions triggered with some database configuration edge cases,Consequence: Lost database transactions,Fix: Retry actions on deadlock conditions,Result: Robust database communication in all cases
- http://www.gossamer-threads.com/lists/openstack/operators/41337?Openstack and mysql galera with haproxy
? ? 文章?Avoiding Deadlocks in Galera - Set up HAProxy for single-node writes and multi-node reads?對這個問題和解決方法有非常詳細的描述。基本原理示意圖:
? 有一個長長的 OpenStack?郵件列表,IMPORTANT: MySQL Galera does *not* support SELECT ... FOR UPDATE?(寫于 2014年五月)中,作者列出了Nova 和 Neutron 中使用的 ?SELECT ... FOR UPDATE 代碼,其中
- Nova 中只有若干地方使用該結構,但是,使用的地方是 quota 代碼中
- Neutron 中大量使用該結構,據(jù)統(tǒng)計,在11個不同的文件中出現(xiàn)了44次。
? 可見,在寫并發(fā)非常高的情況下,死鎖的情況的出現(xiàn)概率是不低的,特別是在 Neutron 中。
? 作者還提出了幾個選項:
4.3.2 一些 workaround
(1)上面的郵件回復中提到的一個 workaround,就是使得更新請求只發(fā)往一個節(jié)點。在使用 HAProxy 的情況下,具體做法是,只設定一個節(jié)點為 master,其余的為 backup。HAProxy 會在 master 失效時自動切換到某一個 backup 上。
server 192.168.0.101 192.168.0.101:3306 checkserver 192.168.0.102 192.168.0.102:3306 check backupserver 192.168.0.103 192.168.0.103:3306 check backup? ? 如果還需要進一步優(yōu)化的話,可以只將寫操作放到一個節(jié)點,而將讀操作在所有節(jié)點之間做負載均衡從而提高性能。Percona XtraDB Cluster reference architecture with HaProxy?描述了一個改進的方案,就是提供兩個 MYSQL 服務端點,一個(端口 3306)只是使用(包括讀寫)一個節(jié)點,另一個(端口3306)使用三個節(jié)點。因此,對 OpenStack 來說,Neutron 使用 3306 端口(如果Nova解決了問題的話),其它組件使用 3307 端口。
global log 127.0.0.1 local0 log 127.0.0.1 local1 notice maxconn 4096 chroot /usr/share/haproxy user haproxy group haproxy daemon defaults log global mode http option tcplog option dontlognull retries 3 option redispatch maxconn 2000 contimeout 5000 clitimeout 50000 srvtimeout 50000frontend pxc-front bind *:3307 mode tcp default_backend pxc-back
frontend stats-front bind *:80 mode http default_backend stats-back
frontend pxc-onenode-front bind *:3306 mode tcp default_backend pxc-onenode-back
backend pxc-back #master-master,適用于沒有使用 SELECT...UPDATE 語句的應用 mode tcp balance leastconn option httpchk server c1 10.116.39.76:3306 check port 9200 inter 12000 rise 3 fall 3 server c2 10.195.206.117:3306 check port 9200 inter 12000 rise 3 fall 3 server c3 10.202.23.92:3306 check port 9200 inter 12000 rise 3 fall 3
backend stats-back mode http balance roundrobin stats uri /haproxy/stats stats auth pxcstats:secret
backend pxc-onenode-back #一個master,其它是backup,用來避免deadlock mode tcp balance leastconn option httpchk server c1 10.116.39.76:3306 check port 9200 inter 12000 rise 3 fall 3 server c2 10.195.206.117:3306 check port 9200 inter 12000 rise 3 fall 3 backup server c3 10.202.23.92:3306 check port 9200 inter 12000 rise 3 fall 3 backup
? (2)另外一個方案是,將 OpenStack 所有的MySQL 操作按照讀和寫做分離(read write splitting),寫只在那個主節(jié)點上,讀在所有節(jié)點上做負載均衡。但是,目前 OpenStack 應該還沒有原生的支持。一個可選的方案是使用開源軟件 maxscale:https://www.percona.com/blog/2015/06/08/maxscale-a-new-tool-to-solve-your-mysql-scalability-problems/
(3)關于 openstack 里面的讀寫分離,其 db 庫 oslo 倒是有了接口支持:
def get_session(self, use_slave=False, **kwargs):
"""Get a Session instance.
:param use_slave: if possible, use 'slave' database connection for?this session. If the connection string for the?slave database wasn't provided, a session bound?to the 'master' engine will be returned.?(defaults to False)
:type use_slave: bool
但是從代碼(Kilo版本)來看,只有 Nova 支持這種 slave_connection 參數(shù)(\nova\nova\db\sqlalchemy\api.py):
def model_query(context, model,args=None,session=None,use_slave=False,read_deleted=None,project_only=False): if session is None:if CONF.database.slave_connection == '':use_slave = Falsesession = get_session(use_slave=use_slave)而 Neutron 模塊至少在 Kilo 版本中還沒有實現(xiàn)。下面的代碼中,調用 oslo 創(chuàng)建 db session 的時候,根本就沒有傳入?CONF.database.slave_connection 的值:
def get_session(autocommit=True, expire_on_commit=False):"""Helper method to grab session."""facade = _create_facade_lazily()return facade.get_session(autocommit=autocommit,expire_on_commit=expire_on_commit)在?這個 openstack 郵件列表?中也能確認這個狀態(tài):
Nova is the only project that uses slave_connection option and it was kind of broken: nova bare metal driver uses a separate database and there was no way to use a slave db connection for it.但是,在 Juno 版本中,唯一沒有解決 dead lock 問題的就是 Neutorn,因此,該配置項對解決 Neutron MySQL Galera 死鎖沒有實質性意義。它只對Nova提高DB性能有幫助。關于該配置項,可以參考官方文檔?https://wiki.openstack.org/wiki/Slave_usage。
4.3.3 對該問題的終極處理
? ? OpenStack 的 Nova 和 Neutorn 模塊都在不少地方使用了?SELECT... FOR UPDAT 語句,可以參考?A lock-free quota implementation?文章中的描述。因此,如果不想使用上面的 Workaround(它降低了對擴展性的支持)而要做終極處理的話,就需要修改Nova 和 Neutron 的代碼將這些語句替換掉了。
? ? 關于代碼修改,有如下文檔:
[documented]:
https://github.com/openstack/nova/blob/da59d3228125d7e7427c0ba70180db17c597e8fb/nova/openstack/common/db/sqlalchemy/session.py#L180-196?
[Nova]:?
http://specs.openstack.org/openstack/nova-specs/specs/kilo/approved/lock-free-quota-management.html?
https://bugs.launchpad.net/oslo.db/+bug/1394298?Galera deadlock on SELECT FOR UPDATE is not handled。這個針對 Nova 的 fix 已經(jīng)進了 Kilo 版本。
[Neutron]:?
https://bugs.launchpad.net/neutron/+bug/1364358https://bugs.launchpad.net/neutron/+bug/1331564
https://bugs.launchpad.net/neutron/+bug/1364358?Remove SELECT FOR UPDATE usage。該 ticket 目前還是 incomplete 狀態(tài),而最新的注釋 “the current design disallows to remove all SELECT FOR UPDATE so the right bug would to ensure all SELECT FOR UPDATE are Galera multi-writers compliant” 更是說明Neutron 這部分的修改還沒有完成。因此,對于 Neutron 來說,還得繼續(xù)使用 workaround。
根據(jù) Mirantis 和 Percona 的 這個報告,Juno 版本中,“All components except neutron are good with using multiple writers”。
4.3.4 數(shù)據(jù)最終一致性問題
這個 OpenStack 郵件列表 描述了該問題:
A: start transaction; A: insert into foo values(1) A: commit; B: select * from foo; <-- May not contain the value we inserted above[3]這說明,雖然 Galera 是生成同步的,但是作為分布式數(shù)據(jù)庫,本質上還是需要一些時間,即使非常短,完成寫入的數(shù)據(jù)同步到整個集群的。因此,在某些情況下,特別是MySQL 負載很大導致同步壓力很大的情況下,這種讀寫不一致性的問題可能會更加突出。
注意最下面右側的Node1 和 node2 上的箭頭和紅線直接的差距(藍色圓圈內),這也是為什么是 “virtually”同步,而不是直接同步。如果正好在gap時間段內讀的話,是無法讀到寫入的數(shù)據(jù)的。
好在 MySQL Galera 提供了一個配置項?wsrep_sync_wait,它的含義是 “Defines whether the node enforces strict cluster-wide causality checks.” ,可以有如下值:
| 0 | Disabled. |
| 1 | Checks on?READ?statements, including?SELECT,?SHOW, and?BEGIN?/?STARTTRANSACTION. |
| 2 | Checks made on?UPDATE?and?DELETE?statements. |
| 3 | Checks made on?READ,?UPDATE?and?DELETE?statements. |
| 4 | Checks made on?INSERT?and?REPLACE?statements. |
它的默認值是0,如果需要保證讀寫一致性可以設置為1。但是需要注意的是,該設置會帶來相應的延遲性,因此,它是一把雙刃劍,到底對性能有多大的影響,需要經(jīng)過測試才能使用。關于該配置項和其它 wresp 配置項的具體說明,可以參考?http://galeracluster.com/documentation-webpages/mysqlwsrepoptions.html。注意到?Mirantis 和 Percona 的?這個報告?所使用的測試環(huán)境中該值被設為1了。
?4.3.5 小結
? 看起來,目前至少Neutron 還沒有完成代碼修改,Nova 中的代碼修改看似已經(jīng)完成,但是需要通過測試來驗證。因此,目前情況下,我們還是需要使用 4.3.1 中描述的 workaround。
?
參考鏈接:
- http://leejia.blog.51cto.com/4356849/841084
- http://drbd.linbit.com/
- http://kafecho.github.io/presentations/introduction-to-pacemaker/#/8
- http://chuansong.me/n/412792
- http://www.gpfeng.com/?p=603
- http://fengchj.com/?p=2273
- http://imysql.com/2015/09/14/solutions-of-mysql-ha.shtml?
- http://www.joinfu.com/2015/01/understanding-reservations-concurrency-locking-in-nova/
- http://www.clusterdb.com/mysql/choosing-the-right-mysql-high-availability-solution-webinar-replay
- http://galeracluster.com/documentation-webpages/mysqlwsrepoptions.html
?
轉載于:https://www.cnblogs.com/sammyliu/p/4995868.html
總結
以上是生活随笔為你收集整理的理解 OpenStack 高可用(HA) (6): MySQL HA的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 系统启动 之 Linux系统启动概述(2
- 下一篇: Untiy3D Material 材质