MySQL8.0.19 MGR MySQL router MySQL connector failover 組合實現高可用

首先在虛擬機中搭建3臺Linux(Redhat8.0)服務器,分別命名爲server01,server02,server03

在每臺虛擬機中安裝好MySQL8.0.19,server_id分別設置爲1,2,3,每臺數據庫創建複製賬戶,並且安裝好組複製插件

set sql_log_bin=0;
create user 'repl'@'%' identified with mysql_native_password by 'repl';
grant replication slave on *.* to 'repl'@'%';
change master to master_user='repl',master_password='repl' for channel 'group_replication_recovery';
set sql_log_bin=1;
install plugin group_replication soname 'group_replication.so';

3臺服務器對應的IP如下:

192.168.56.10 server01
192.168.56.11 server02
192.168.56.12 server03

server01 my.cnf 設置

[mysqld]

basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
socket = /tmp/mysql.sock
log-error = /usr/local/mysql/data/error.log
log_timestamps=SYSTEM
pid-file = /usr/local/mysql/data/mysql.pid
tmpdir = /tmp
secure-file-priv=/tmp
port = 3306
server_id = 1
max_allowed_packet=32M
log_bin_trust_function_creators = ON
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

master_info_repository=TABLE
relay_log_info_repository=TABLE
gtid_mode=ON
enforce_gtid_consistency=ON
binlog_checksum=NONE
transaction_isolation=READ-COMMITTED
transaction_write_set_extraction=XXHASH64
slave_preserve_commit_order=ON

group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
group_replication_local_address= "192.168.56.10:33006"
group_replication_group_seeds= "192.168.56.10:33006,192.168.56.11:33006,192.168.56.12:33006"
group_replication_start_on_boot=on
group_replication_bootstrap_group=on
group_replication_ip_whitelist='192.168.56.0/24'
group_replication_member_weight=90

因爲我這裏是虛擬機,所以設置server01 group_replication_bootstrap_group=on,每次虛擬機啓動的時候設置server01爲主節點

server01數據庫啓動之後設置set global group_replication_bootstrap_group=off;

vi my.cnf group_replication_bootstrap_group=off

server02 my.cnf 設置

[mysqld]
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
socket = /tmp/mysql.sock
log-error = /usr/local/mysql/data/error.log
log_timestamps=SYSTEM
pid-file = /usr/local/mysql/data/mysql.pid
tmpdir = /tmp
secure-file-priv=/tmp
port = 3306
server_id = 2
max_allowed_packet=32M
log_bin_trust_function_creators = ON
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

master_info_repository=TABLE
relay_log_info_repository=TABLE
gtid_mode=ON
enforce_gtid_consistency=ON
binlog_checksum=NONE
transaction_isolation=READ-COMMITTED
transaction_write_set_extraction=XXHASH64
slave_preserve_commit_order=ON

group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
group_replication_local_address= "192.168.56.11:33006"
group_replication_group_seeds= "192.168.56.10:33006,192.168.56.11:33006,192.168.56.12:33006"
group_replication_start_on_boot=on
group_replication_bootstrap_group=off
group_replication_ip_whitelist='192.168.56.0/24'
group_replication_member_weight=80

server03 my.cnf 設置

[mysqld]
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
socket = /tmp/mysql.sock
log-error = /usr/local/mysql/data/error.log
log_timestamps=SYSTEM
pid-file = /usr/local/mysql/data/mysql.pid
tmpdir = /tmp
secure-file-priv=/tmp
port = 3306
server_id = 3
max_allowed_packet=32M
log_bin_trust_function_creators = ON
sql_mode=NO_ENGINE_SUBSTITUTION,STRICT_TRANS_TABLES

master_info_repository=TABLE
relay_log_info_repository=TABLE
gtid_mode=ON
enforce_gtid_consistency=ON
binlog_checksum=NONE
transaction_isolation=READ-COMMITTED
transaction_write_set_extraction=XXHASH64
slave_preserve_commit_order=ON

group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
group_replication_local_address= "192.168.56.12:33006"
group_replication_group_seeds= "192.168.56.10:33006,192.168.56.11:33006,192.168.56.12:33006"
group_replication_start_on_boot=on
group_replication_bootstrap_group=off
group_replication_ip_whitelist='192.168.56.0/24'

依次重啓server01,server02,server03的數據庫,然後執行,可以看到單主模式的MGR集羣已經搭建成功

start group_replication;
select * from performance_schema.replication_group_members\G

mysql> select * from performance_schema.replication_group_members\G
*************************** 1. row ***************************
  CHANNEL_NAME: group_replication_applier
     MEMBER_ID: 5d9c8647-a23d-11ea-9364-080027bc623e
   MEMBER_HOST: server03
   MEMBER_PORT: 3306
  MEMBER_STATE: ONLINE
   MEMBER_ROLE: SECONDARY
MEMBER_VERSION: 8.0.19
*************************** 2. row ***************************
  CHANNEL_NAME: group_replication_applier
     MEMBER_ID: ac825c32-a23b-11ea-ac18-0800276a9719
   MEMBER_HOST: server02
   MEMBER_PORT: 3306
  MEMBER_STATE: ONLINE
   MEMBER_ROLE: SECONDARY
MEMBER_VERSION: 8.0.19
*************************** 3. row ***************************
  CHANNEL_NAME: group_replication_applier
     MEMBER_ID: be4680a2-a23c-11ea-b64b-080027a9710a
   MEMBER_HOST: server01
   MEMBER_PORT: 3306
  MEMBER_STATE: ONLINE
   MEMBER_ROLE: PRIMARY
MEMBER_VERSION: 8.0.19
3 rows in set (0.00 sec)

在server01和server03上安裝MySQL router(本來應該是在應用程序的服務器上安裝MySQL router)

我這裏是用Python來測試,而非Java,所以就把MySQL router裝在了數據庫服務器上

爲什麼要裝2個MySQL router呢?因爲MySQL router如果是單個的話存在單點故障

雖然數據庫是3個集羣HA,但是如果MySQL router掛了,應用就連不上數據庫了,所以裝2個MySQL router

分別在server01以及server03上安裝MySQL router

xz -d mysql-router-8.0.19-linux-glibc2.12-x86_64.tar.xz
tar -xvf mysql-router-8.0.19-linux-glibc2.12-x86_64.tar
mv mysql-router-8.0.19-linux-glibc2.12-x86_64 /usr/local/mysql-router-8.0.19

vi /etc/profile

export PATH=$PATH:/usr/local/mysql-router-8.0.19/bin

source /etc/profile

配置MySQL Router

cd /usr/local/mysql-router-8.0.19/
mkdir log
mkdir data
chown -R mysql:mysql  /usr/local/mysql-router-8.0.19/

vi /etc/mysqlrouter.conf

[DEFAULT]
logging_folder = /usr/local/mysql-router-8.0.19/log
plugin_folder = /usr/local/mysql-router-8.0.19/lib/mysqlrouter
data_folder=/usr/local/mysql-router-8.0.19/data

[logger]
level = INFO

[routing:primary]
bind_address = 0.0.0.0
bind_port = 7001
destinations = 192.168.56.10:3306,192.168.56.11:3306
routing_strategy = first-available
 
[routing:secondary]
bind_address = 0.0.0.0
bind_port = 7002
destinations = 192.168.56.11:3306 ,192.168.56.12:3306
routing_strategy = round-robin

chown mysql:mysql /etc/mysqlrouter.conf

啓動MySQL Router
mysqlrouter --config=/etc/mysqlrouter.conf &

我這裏選擇Python來測試MySQL router + MGR 高可用,首先安裝mysql-connector-python

不要用pymysql,因爲pymysql沒有實現failover

pip install mysql-connector-python

failover測試代碼:

import mysql.connector
conn = mysql.connector.connect(user='scott', password='tiger',
                               host='192.168.56.10',
                               port=7001,
                               database='test',
                               connect_timeout=0.05,
                               failover=([{'user': 'scott'}, {'password': 'tiger'}, {'host': '192.168.56.12'},{'port': 7001}, {'database': 'test'}])
                               )
cur=conn.cursor()

sql2='select @@hostname'
cur.execute(sql2)
for result in cur:
  print('Python連接上了:'+result[0])
sql1="update emp set ename='沙雕' where empno=9900"
cur.execute(sql1)
print('數據更新成功')
cur.close()
conn.commit()

測試連接

C:\Users\Robinson>cd c:\Python\project

c:\Python\project>py test.py
Python連接上了:server01
數據更新成功

c:\Python\project>py test.py
Python連接上了:server01
數據更新成功

c:\Python\project>py test.py
Python連接上了:server01
數據更新成功

現在把server01虛擬機關閉,MGR集羣還剩下2個節點,server01上的MySQL router也掛了,只剩下server03上的router

mysql> select * from performance_schema.replication_group_members\G
*************************** 1. row ***************************
  CHANNEL_NAME: group_replication_applier
     MEMBER_ID: 5d9c8647-a23d-11ea-9364-080027bc623e
   MEMBER_HOST: server03
   MEMBER_PORT: 3306
  MEMBER_STATE: ONLINE
   MEMBER_ROLE: SECONDARY
MEMBER_VERSION: 8.0.19
*************************** 2. row ***************************
  CHANNEL_NAME: group_replication_applier
     MEMBER_ID: ac825c32-a23b-11ea-ac18-0800276a9719
   MEMBER_HOST: server02
   MEMBER_PORT: 3306
  MEMBER_STATE: ONLINE
   MEMBER_ROLE: PRIMARY
MEMBER_VERSION: 8.0.19
2 rows in set (0.00 sec)

測試連接

c:\Python\project>py test.py
Python連接上了:server02
數據更新成功

c:\Python\project>py test.py
Python連接上了:server02
數據更新成功

c:\Python\project>py test.py
Python連接上了:server02
數據更新成功

因爲我在server02上設置了group_replication_member_weight=80,而server03 group_replication_member_weight=50

所以server01掛了會自動選擇server02作爲主節點

現在重新啓動server01虛擬機看一下MGR集羣

mysql> select * from performance_schema.replication_group_members\G
*************************** 1. row ***************************
  CHANNEL_NAME: group_replication_applier
     MEMBER_ID: 5d9c8647-a23d-11ea-9364-080027bc623e
   MEMBER_HOST: server03
   MEMBER_PORT: 3306
  MEMBER_STATE: ONLINE
   MEMBER_ROLE: SECONDARY
MEMBER_VERSION: 8.0.19
*************************** 2. row ***************************
  CHANNEL_NAME: group_replication_applier
     MEMBER_ID: ac825c32-a23b-11ea-ac18-0800276a9719
   MEMBER_HOST: server02
   MEMBER_PORT: 3306
  MEMBER_STATE: ONLINE
   MEMBER_ROLE: PRIMARY
MEMBER_VERSION: 8.0.19
*************************** 3. row ***************************
  CHANNEL_NAME: group_replication_applier
     MEMBER_ID: be4680a2-a23c-11ea-b64b-080027a9710a
   MEMBER_HOST: server01
   MEMBER_PORT: 3306
  MEMBER_STATE: ONLINE
   MEMBER_ROLE: SECONDARY
MEMBER_VERSION: 8.0.19
3 rows in set (0.00 sec)

啓動server01上的MySQL router

注意,注意,注意,直接啓動MySQL router 你會沙雕,變成超級大沙雕

MySQL router裏面配置的是

[routing:primary]
bind_address = 0.0.0.0
bind_port = 7001
destinations = 192.168.56.10:3306,192.168.56.11:3306
routing_strategy = first-available

要將destinations = 192.168.56.10:3306,192.168.56.11:3306
改成destinations = 192.168.56.11:3306,192.168.56.10:3306

現在只有server02能對外提供DML,如果不更改MySQL router配置,應用連接到server01執行DML會報錯

所以編寫一個shell腳本來啓動MySQL router

[root@server01 ~]# cat start_router.sh
#!/bin/bash

var1=`grep -r "destinations"  /etc/mysqlrouter.conf | head -1`
var2=`mysql -N -e "select  case
                     when member_host='server02' then
                      'destinations =192.168.56.11:3306,192.168.56.10:3306'
                     when member_host='server01' then
                      'destinations =192.168.56.10:3306,192.168.56.11:3306'
                           end destinations
                   from performance_schema.replication_group_members where member_role='PRIMARY'"`


sed -i "s/$var1/$var2/g" /etc/mysqlrouter.conf
ps -ef |grep mysqlrouter | grep -v grep | kill -9  `awk {'print $2'}`
mysqlrouter --config=/etc/mysqlrouter.conf &

需要注意的是,只有當server01上的MySQL數據庫啓動了再來啓動MySQL router,我的shell裏面沒考慮這個

[root@server01 ~]# sh start_router.sh
kill: usage: kill [-s sigspec | -n signum | -sigspec] pid | jobspec ... or kill -l [sigspec]
[root@server01 ~]# logging facility initialized, switching logging to loggers specified in configuration

測試連接

c:\Python\project>py test.py
Python連接上了:server02
數據更新成功

c:\Python\project>py test.py
Python連接上了:server02
數據更新成功

c:\Python\project>py test.py
Python連接上了:server02
數據更新成功

 

 

 

 

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