MySQL MGR+ Consul之數據庫高可用方案

背景說明: 
    基於目前存在不少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集羣環境搭建 (單主模式)

MGR的搭建請參考http://www.javashuo.com/article/p-yqedotet-k.htmlweb

 

搭建consul 使其mysql-primary和mysql-slave 註冊到服務發現上 

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

 

構建bind域名解析:

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

 http://www.imooc.com/article/274897

http://www.cnblogs.com/gomysql/p/8010552.html

相關文章
相關標籤/搜索