背景說明:
基於目前存在不少MySQL數據庫單點故障,傳統的MHA,PXC等方案用VIP或者DNS切換的方式能夠實現、基於數據庫的數據強一致性考慮,採用MGR集羣,採用consul服務註冊發現實現應用端經過動態DNS 訪問MGR集羣,實現數據庫高可用,自動化切換的方案
MGR簡介 html
MySQL Group Replication(MGR)是MySQL官方在5.7.17版本引進的一個數據庫高可用與高擴展的解決方案,以插件形式提供,實現了分佈式下數據的最終一致性,總結MGR特色以下:
高一致性:基於分佈式paxos協議實現組複製,保證數據一致性;
高容錯性:自動檢測機制,只要不是大多數節點都宕機就能夠繼續工做,內置防腦裂保護機制;
高擴展性:節點的增長與移除會自動更新組成員信息,新節點加入後,自動從其餘節點同步增量數據,直到與其餘節點數據一致;
高靈活性:提供單主模式和多主模式,單主模式在主庫宕機後可以自動選主,全部寫入都在主節點進行,多主模式支持多節點寫入。
MGR原理說明:
組複製是一種可用於實現容錯系統的技術。 複製組是一個經過消息傳遞相互交互的 server 集羣。通訊層提供了原子消息(atomic message)和徹底有序信息交互等保障機制
實現了基於複製協議的多主更新
複製組由多個 server成員構成,而且組中的每一個 server 成員能夠獨立地執行事務。但全部讀寫(RW)事務只有在衝突檢測成功後纔會提交。只讀(RO)事務不須要在衝突檢測,能夠當即提交。句話說,對於任何 RW 事務,提交操做並非由始發 server 單向決定的,而是由組來決定是否提交。準確地說,在始發 server 上,當事務準備好提交時,該 server 會廣播寫入值(已改變的行)和對應的寫入集(已更新的行的惟一標識符)。而後會爲該事務創建一個全局的順序。最終,這意味着全部 server 成員以相同的順序接收同一組事務。所以,全部 server 成員以相同的順序應用相同的更改,以確保組內一致。組複製是一種 share-nothing 複製方案,其中每一個 server 成員都有本身的完整數據副本。 node
MGR的侷限性:
僅支持InnodDB存儲引擎的表,而且每一個表必須有主鍵ID, 用作wirte set的衝突檢測
必須啓用GTID特性,binlog日誌格式必須爲row模式
目前一個MGR集羣最多支持9個節點
不支持外健的save point特性,沒法作全局間的約束檢測和部分回滾
二進制日誌不支持binlog event checksum mysql
consul簡介
微服務架構中很是重的一個模塊,提供服務註冊、服務發現等,經常使用的服務發現模塊有,zookeeper、enreka、etcd、cunsul等。
cousul是分佈式、高可用、可橫向發展的中間鍵,其特性以下:
一、service discovery:經過dns或者http接口提供服務註冊和發現
二、health checking:自帶健康檢查,可提供服務故障時的轉移
三、key/value storage:可存儲動態配置的系統,提供http接口,
四、multi-datacenter:能夠支持多數據中心
環境說明:
192.168.202.177 consul server 目前只部署了一個server,可部署集羣模式
192.168.202.174 mysql server node一、consul client
192.168.202.175 mysql server node二、consul client
192.168.202.176 mysql server node三、consul client
系統版本:centos 7.5
Mysql version:5.7.25
consul version:1.4.4 git
MGR的搭建請參考http://www.javashuo.com/article/p-yqedotet-k.htmlweb
consul-server:192.168.202.177
consul-client:192.168.202.17四、192.168.202.17五、192.168.202.176sql
在官網:https://www.consul.io/downloads.html下載對應的版本,解壓後copy consul 到/usr/local/bin/下便可
分別在4臺機器上安裝而後運行
mkdir -pv /etc/consul.d/ && mkdir -pv /data/consul/
mkdir -pv /data/consul/shellshell
在consul server 192.168.202.177上 編寫配置文件數據庫
[root@consul-server consul]# cat /etc/consul.d/server.json { "data_dir": "/data/consul", "datacenter": "dc1", "log_level": "INFO", "server": true, "node_name": "Server", "bootstrap_expect": 1, "bind_addr": "192.168.202.177", "client_addr": "192.168.202.177", "ui":true }
在consul client 192.168.202.17四、192.168.202.17五、192.168.202.176上編寫配置文件,三臺服務器的上bind_addr 修改成響應IP便可 json
[root@node1 consul]# cat /etc/consul.d/client.json { "data_dir": "/data/consul", "enable_script_checks": true, "bind_addr": "192.168.202.174", "retry_join": ["192.168.202.177"], "retry_interval": "30s", "rejoin_after_leave": true, "start_join": ["192.168.202.177"] , "node_name": "node1" }
在consul client 192.168.202.17四、192.168.202.17五、192.168.202.176上編寫檢測primay 腳本 和檢測slave 腳本 bootstrap
[root@node1 consul]# cat /data/consul/shell/check_mysql_mgr_master.sh #!/bin/bash port=3306 user="root" passwod="iforgot" comm="/usr/local/mysql/bin/mysql -u$user -hlocalhost -P $port -p$passwod" value=`$comm -Nse "select 1"` primary_member=`$comm -Nse "select variable_value from performance_schema.global_status WHERE VARIABLE_NAME= 'group_replication_primary_member'"` server_uuid=`$comm -Nse "select variable_value from performance_schema.global_variables where VARIABLE_NAME='server_uuid';"` # 判斷MySQL是否存活 if [ -z $value ] then echo "mysql $port is down....." exit 2 fi # 判斷節點狀態,是否存活 node_state=`$comm -Nse "select MEMBER_STATE from performance_schema.replication_group_members where MEMBER_ID='$server_uuid'"` if [ $node_state != "ONLINE" ] then echo "MySQL $port state is not online...." exit 2 fi # 判斷是否是主節點 if [[ $server_uuid == $primary_member ]] then echo "MySQL $port Instance is master ........" exit 0 else echo "MySQL $port Instance is slave ........" exit 2 fi
[root@node1 consul]# cat /data/consul/shell/check_mysql_mgr_slave.sh #!/bin/bash port=3306 user="root" passwod="iforgot" comm="/usr/local/mysql/bin/mysql -u$user -hlocalhost -P $port -p$passwod" value=`$comm -Nse "select 1"` primary_member=`$comm -Nse "select variable_value from performance_schema.global_status WHERE VARIABLE_NAME= 'group_replication_primary_member'"` server_uuid=`$comm -Nse "select variable_value from performance_schema.global_variables where VARIABLE_NAME='server_uuid';"` # 判斷mysql是否存活 if [ -z $value ] then echo "mysql $port is down....." exit 2 fi # 判斷節點狀態 node_state=`$comm -Nse "select MEMBER_STATE from performance_schema.replication_group_members where MEMBER_ID='$server_uuid'"` if [ $node_state != "ONLINE" ] then echo "MySQL $port state is not online...." exit 2 fi # 判斷是否是主節點 if [[ $server_uuid != $primary_member ]] then echo "MySQL $port Instance is slave ........" exit 0 else node_num=`$comm -Nse "select count(*) from performance_schema.replication_group_members"` # 判斷若是沒有任何從節點,主節點也註冊從角色服務。 if [ $node_num -eq 1 ] then echo "MySQL $port Instance is slave ........" exit 0 else echo "MySQL $port Instance is master ........" exit 2 fi fi
啓動consul server 在192.168.202.177上
nohup consul agent -config-dir=/etc/consul.d > /data/consul/consul.log &
啓動consul client 在192.168.202.17四、192.168.202.17五、192.168.202.176
nohup consul agent -config-dir=/etc/consul.d > /data/consul/consul.log &
觀察consul server的log日誌3個client自動註冊到了consul上了
查看consul成員
[root@consul-server consul]# consul members -http-addr='192.168.202.177:8500' Node Address Status Type Build Protocol DC Segment Server 192.168.202.177:8301 alive server 1.4.4 2 dc1 <all> node1 192.168.202.174:8301 alive client 1.4.4 2 dc1 <default> node2 192.168.202.175:8301 alive client 1.4.4 2 dc1 <default> node3 192.168.202.176:8301 alive client 1.4.4 2 dc1 <default>
訪問consulserver的web頁面 http://192.168.202.177:8500/ui/
到此爲止consul 集羣已經搭建成功了
下面咱們繼續爲實現mysql的高可用集羣
MGR+Consul高可用實現
檢測MGR集羣狀態
查看那個是主節點
基於不一樣consul版本配置可能不太同樣,三臺機器都須要相應的json腳本檢測mysql是否爲主或從,配置文件修改相應的IP便可使用
查看consul server ui界面便可看到三臺mysql的mgr集羣已經註冊到consul服務上了
注意:因爲每臺mysql server 上都有master、slave 檢測腳本、而mysql server 只能是master 或者slave、因此存在失敗的檢測,master檢測只有一個成功,slave檢測只有一個失敗
consul dns配置
查看dns信息
App端配置域名服務器IP來解析consul後綴的域名,DNS解析及跳轉, 有三個方案:
1. 原內網dns服務器,作域名轉發,consul後綴的,都轉到consul server上,目前採用的這種方式
2. dns所有跳到consul DNS服務器上,非consul後綴的,使用 recursors 屬性跳轉到原DNS服務器上
3. dnsmaq 轉: server=/consul/10.16.X.X#8600 解析consul後綴的
咱們內網dns是用的bind,對於bind的如何作域名轉發consul官網也有栗子:https://www.consul.io/docs/guides/forwarding.html
yum install bind -y
配置name服務作解析:
[root@consul-server consul]# cat /etc/named.conf // // named.conf // // Provided by Red Hat bind package to configure the ISC BIND named(8) DNS // server as a caching only nameserver (as a localhost DNS resolver only). // // See /usr/share/doc/bind*/sample/ for example named configuration files. // // See the BIND Administrator's Reference Manual (ARM) for details about the // configuration located in /usr/share/doc/bind-{version}/Bv9ARM.html options { listen-on port 53 { 192.168.202.177; }; listen-on-v6 port 53 { ::1; }; directory "/var/named"; dump-file "/var/named/data/cache_dump.db"; statistics-file "/var/named/data/named_stats.txt"; memstatistics-file "/var/named/data/named_mem_stats.txt"; recursing-file "/var/named/data/named.recursing"; secroots-file "/var/named/data/named.secroots"; allow-query { any; }; /* - If you are building an AUTHORITATIVE DNS server, do NOT enable recursion. - If you are building a RECURSIVE (caching) DNS server, you need to enable recursion. - If your recursive DNS server has a public IP address, you MUST enable access control to limit queries to your legitimate users. Failing to do so will cause your server to become part of large scale DNS amplification attacks. Implementing BCP38 within your network would greatly reduce such attack surface */ recursion yes; dnssec-enable no; dnssec-validation no; /* Path to ISC DLV key */ bindkeys-file "/etc/named.iscdlv.key"; managed-keys-directory "/var/named/dynamic"; pid-file "/run/named/named.pid"; session-keyfile "/run/named/session.key"; }; logging { channel default_debug { file "data/named.run"; severity dynamic; }; }; zone "." IN { type hint; file "named.ca"; }; include "/etc/named.rfc1912.zones"; include "/etc/named.root.key"; include "/etc/named/consul.conf";
[root@consul-server consul]# cat /etc/named/consul.conf zone "consul" IN { type forward; forward only; forwarders { 192.168.202.177 port 8600; }; };
[root@consul-server consul]# cat /etc/resolv.conf # Generated by NetworkManager search localdomain nameserver 192.168.202.177 [root@consul-server consul]# systemctl start named [root@consul-server consul]# systemctl enable named
參考來源:
http://blog.itpub.net/29987453/viewspace-2637608/
https://blog.51cto.com/xiaoluoge/2134126
http://www.javashuo.com/article/p-ysmyazxb-gy.html