基於MySQL innodb cluster和MySQL router的高可用與讀寫分離


1.背景

2016年12月12日MySQL5.7.17版本GA了。其中最重要的一個新特性是,官方的高可用架構組復制(Group Replication)。
2017年4月份,基於組復制的一套完整的官方的MySQL高可用解決方案誕生了,這就是這篇文章要介紹的MySQL innodb
cluster。
運維同事搭建MySQL數據庫高可用時又多了一套架構可以選擇了。
而本文章,我們會更深入一些,帶大家從零開始搭建完整的基於MySQL innodb cluster和MySQL router的高可用與讀寫分離的架構。

注意,文中實現的架構基於MGR的單主架構,而非多主架構。多主架構有一些坑,暫不推薦多主。文中單主架構采用的是最簡單的三台mysqld服務器實現,讀寫分離為主提供寫,兩個從提供讀。

2.架構圖

3.基礎環境

3.1 軟硬件准備

三台數據庫服務器:
192.168.199.121
192.168.199.122
192.168.199.123
一台應用服務器
192.168.199.198

規格:
系統:centos 7.5  
MySQL:8.0.13 二進制包  
MySQL shell: 8.0.13 二進制包  
MySQL router: 8.0.13 二進制包  

3.2 四台機hosts 修改

vi /etc/hosts
192.168.199.121 192-168-199-121
192.168.199.122 192-168-199-122
192.168.199.123 192-168-199-123

#應用服務器所在的host關系可以不配置進去,但應用服務器也要修改hosts文件

3.3 關閉防火牆和SELINUX

#關閉selinux
#selinux配置文件修改
vim /etc/selinux/config
SELINUX=disabled

#臨時在線關閉selinux
setenforce 0

#關閉防火牆
systemctl stop firewalld
systemctl disable firewalld

4.開始搭建

4.1 MySQL組復制的搭建

#下載MySQL 8.0.13二進制安裝包
wget https://dev.mysql.com/get/Downloads/MySQL-8.0/mysql-8.0.13-linux-glibc2.12-x86_64.tar.xz
#解壓安裝二進制程序
mkdir -p /opt/mysql-8.0
tar Jxvf mysql-8.0.13-linux-glibc2.12-x86_64.tar.xz -C /opt/mysql-8.0/ && cd  /opt/mysql-8.0/mysql-8.0.13-linux-glibc2.12-x86_64 && mv *  .. && ln -s /opt/mysql-8.0/ /usr/local/mysql
#添加mysql組和mysql用戶
groupadd mysql 
useradd -M -g mysql -s /sbin/nologin -d /usr/local/mysql mysql
#創建MySQL數據目錄
mkdir -p /database/mysql/data/3306
chown mysql:mysql /database/mysql/data/3306 -R

#修改加入環境變量
echo  'export PATH=/usr/local/mysql/bin/:$PATH' >>/etc/profile
source /etc/profile
#編輯配置文件 vi /etc/my.cnf
# “#”號右邊的是MySQL官方默認值
[mysql]
auto-rehash
socket                              =/tmp/mysql.sock                #   /tmp/mysql.sock


[mysqld]
####: for global
user                                =mysql                          #	mysql
basedir                             =/usr/local/mysql/              #	/usr/local/mysql/
datadir                             =/database/mysql/data/3306      #	/usr/local/mysql/data
server_id                           =647                            #	0
port                                =3306                           #	3306
character_set_server                =utf8                           #	latin1
log_bin_trust_function_creators     =on                             #   0
max_prepared_stmt_count             =1048576
log_timestamps                      =system                         #	utc
socket                              =/tmp/mysql.sock                #	/tmp/mysql.sock
read_only                           =0                              #	off
skip_name_resolve                   =1                              #   0
auto_increment_increment            =1                              #	1
auto_increment_offset               =1                              #	1
lower_case_table_names              =1                              #	0
secure_file_priv                    =                               #	null
open_files_limit                    =65536                          #   1024
max_connections                     =1000
thread_cache_size                   =256                              #   9
table_open_cache                    =4096                           #   2000
table_definition_cache              =2000                           #   1400
table_open_cache_instances          =32                             #   16

####: for binlog
binlog_format                       =row                          #	row
log_bin                             =mysql-bin                      #	off
binlog_rows_query_log_events        =on                             #	off
log_slave_updates                   =on                             #	off
expire_logs_days                    =7                              #	0
binlog_cache_size                   =65536                          #	65536(64k)
binlog_checksum                     =none                           #	CRC32
sync_binlog                         =1                              #	1
slave-preserve-commit-order         =ON                             #   

####: for error-log
log_error                           =err.log                        #	/usr/local/mysql/data/localhost.localdomain.err

general_log                         =off                            #   off
general_log_file                    =general.log                    #   hostname.log

####: for slow query log
slow_query_log                      =on                             #    off
slow_query_log_file                 =slow.log                       #    hostname.log
log_queries_not_using_indexes       =on                             #    off
long_query_time                     =10.000000                       #    10.000000

####: for gtid
gtid_executed_compression_period    =1000                          #	1000
gtid_mode                           =on                            #	off
enforce_gtid_consistency            =on                            #	off


####: for replication
skip_slave_start                    =0                              #	
master_info_repository              =table                         #	file
relay_log_info_repository           =table                         #	file
slave_parallel_type                 =logical_clock                 #    database | LOGICAL_CLOCK
slave_parallel_workers              =2                             #    0
rpl_semi_sync_master_enabled        =1                             #    0
rpl_semi_sync_slave_enabled         =1                             #    0
rpl_semi_sync_master_timeout        =1000                          #    1000(1 second)
plugin_load_add                     =semisync_master.so            #
plugin_load_add                     =semisync_slave.so             #
binlog_group_commit_sync_delay      =500                          #    500(0.05%秒)、默認值0
binlog_group_commit_sync_no_delay_count = 13                        #    0


####: for innodb
default_storage_engine                          =innodb                     #	innodb
default_tmp_storage_engine                      =innodb                     #	innodb
innodb_data_file_path                           =ibdata1:64M:autoextend     #	ibdata1:12M:autoextend
innodb_temp_data_file_path                      =ibtmp1:12M:autoextend      #	ibtmp1:12M:autoextend
innodb_buffer_pool_filename                     =ib_buffer_pool             #	ib_buffer_pool
innodb_log_group_home_dir                       =./                         #	./
innodb_log_files_in_group                       =16                          #	2
innodb_log_file_size                            =256M                        #	50331648(48M)
innodb_file_per_table                           =on                         #	on
innodb_online_alter_log_max_size                =128M                  #   134217728(128M)
innodb_open_files                               =65535                       #   2000
innodb_page_size                                =16k                        #	16384(16k)
innodb_thread_concurrency                       =0                          #	0
innodb_read_io_threads                          =4                          #	4
innodb_write_io_threads                         =4                          #	4
innodb_purge_threads                            =4                          #	4(垃圾回收)
innodb_page_cleaners                            =4                          #   4(刷新lru臟頁)
innodb_print_all_deadlocks                      =on                         #	off
innodb_deadlock_detect                          =on                         #	on
innodb_lock_wait_timeout                        =50                         #	50
innodb_spin_wait_delay                          =6                          #	6
innodb_autoinc_lock_mode                        =2                          #	1
innodb_io_capacity                              =200                        #   200
innodb_io_capacity_max                          =2000                       #   2000
#--------Persistent Optimizer Statistics
innodb_stats_auto_recalc                        =on                         #   on
innodb_stats_persistent                         =on                         #	on
innodb_stats_persistent_sample_pages            =20                         #	20
innodb_buffer_pool_instances                    =2
innodb_adaptive_hash_index                      =on                         #	on
innodb_change_buffering                         =all                        #	all
innodb_change_buffer_max_size                   =25                         #	25
innodb_flush_neighbors                          =1                          #	1
#innodb_flush_method                             =                           #	
innodb_doublewrite                              =on                         #	on
innodb_log_buffer_size                          =64M                        #	16777216(16M)
innodb_flush_log_at_timeout                     =1                          #	1
innodb_flush_log_at_trx_commit                  =1                          #	1
innodb_buffer_pool_size                         =2176M                  #	134217728(128M)
autocommit                                      =1                          #	1
#--------innodb scan resistant
innodb_old_blocks_pct                           =37                         #    37
innodb_old_blocks_time                          =1000                       #    1000
#--------innodb read ahead
innodb_read_ahead_threshold                     =56                         #    56 (0..64)
innodb_random_read_ahead                        =OFF                        #    OFF
#--------innodb buffer pool state
innodb_buffer_pool_dump_pct                     =25                         #    25 
innodb_buffer_pool_dump_at_shutdown             =ON                         #    ON
innodb_buffer_pool_load_at_startup              =ON                         #    ON




####  for performance_schema
performance_schema                                                      =on    #    on
performance_schema_consumer_global_instrumentation                      =on    #    on
performance_schema_consumer_thread_instrumentation                      =on    #    on
performance_schema_consumer_events_stages_current                       =on    #    off
performance_schema_consumer_events_stages_history                       =on    #    off
performance_schema_consumer_events_stages_history_long                  =off   #    off
performance_schema_consumer_statements_digest                           =on    #    on
performance_schema_consumer_events_statements_current                   =on    #    on
performance_schema_consumer_events_statements_history                   =on    #    on
performance_schema_consumer_events_statements_history_long              =off   #    off
performance_schema_consumer_events_waits_current                        =on    #    off
performance_schema_consumer_events_waits_history                        =on    #    off
performance_schema_consumer_events_waits_history_long                   =off   #    off
performance-schema-instrument                                           ='memory/%=COUNTED'

要注意組復制的my.cnf以下配置是必須要修改/增加的,三台server分別如下

#組復制前提配置
#192.168.199.121
server_id=121  #三台server分別配置121、122、123
gtid_mode=ON
enforce_gtid_consistency=ON
binlog_checksum=NONE

#組復制配置
loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
loose-group_replication_start_on_boot=off
loose-group_replication_local_address= "192.168.199.121:33061"
loose-group_replication_group_seeds= "192.168.199.121:33061,192.168.199.122:33062,192.168.199.123:33063"
loose-group_replication_bootstrap_group=off
#組復制前提配置
#192.168.199.122
server_id=122  #三台server分別配置121、122、123
gtid_mode=ON
enforce_gtid_consistency=ON
binlog_checksum=NONE

#組復制配置
loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
loose-group_replication_start_on_boot=off
loose-group_replication_local_address= "192.168.199.122:33062"
loose-group_replication_group_seeds= "192.168.199.121:33061,192.168.199.122:33062,192.168.199.123:33063"
loose-group_replication_bootstrap_group=off
#組復制前提配置
#192.168.199.123
server_id=123  #三台server分別配置121、122、123
gtid_mode=ON
enforce_gtid_consistency=ON
binlog_checksum=NONE

#組復制配置
loose-group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
loose-group_replication_start_on_boot=off
loose-group_replication_local_address= "192.168.199.123:33063"
loose-group_replication_group_seeds= "192.168.199.121:33061,192.168.199.122:33062,192.168.199.123:33063"
loose-group_replication_bootstrap_group=off
#無密碼初始化
mysqld --defaults-file=/etc/my.cnf --initialize-insecure 
#啟動數據庫
mysqld --defaults-file=/etc/my.cnf &

#當然也可以用以下做成服務的方式啟動,這樣有mysqld_safe守護進程
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysqld
service mysqld start
#建立組復制
# 192.168.199.121、192.168.199.122、192.168.199.123 同操作
# 直接mysql即可無密碼登錄
mysql

# 以下是SQL
SET SQL_LOG_BIN=0;
CREATE USER rpl_user@'%' IDENTIFIED WITH 'mysql_native_password' BY 'password';
GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
CREATE USER root@'%' IDENTIFIED BY 'root';
GRANT ALL on *.* to root@'%' with grant option;
FLUSH PRIVILEGES;
SET SQL_LOG_BIN=1;

INSTALL PLUGIN group_replication SONAME 'group_replication.so';

SHOW PLUGINS;

CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='password'  FOR CHANNEL 'group_replication_recovery';
# 192.168.199.121 SQL操作
SET GLOBAL group_replication_bootstrap_group=ON;
START GROUP_REPLICATION;
SET GLOBAL group_replication_bootstrap_group=OFF;
# 其他機器,即192.168.199.122、192.168.199.123只需要SQL操作
START GROUP_REPLICATION;

驗證

SELECT * FROM performance_schema.replication_group_members;

192.168.199.121PRIMARY庫上測試一下

#92.168.199.121PRIMARY庫上測試一下
CREATE DATABASE test;
USE test;
CREATE TABLE t1 (c1 INT PRIMARY KEY, c2 TEXT NOT NULL);
INSERT INTO t1 VALUES (1, 'Luis');

#三台都執行驗證一下gtid是否增加
show master status\G
SELECT * FROM performance_schema.replication_group_members;

於是組復制搭建完畢。

4.2 MySQL Shell的部署

MySQL Shell,它是一個支持MySQL服務器開發和管理的交互式JavaScript,Python或SQL接口。MySQL Shell是一個可以單獨安裝的組件,是安裝和管理MySQL innodb cluster必須安裝的組件,以下文中將用js模式操作。

192.168.199.121PRIMARY庫上部署mysql-shell,或三台MGR主機都部署mysql-shell

#下載mysql-shell二進制安裝包
wget https://dev.mysql.com/get/Downloads/MySQL-Shell/mysql-shell-8.0.13-linux-glibc2.12-x86-64bit.tar.gz
mkdir -p /opt/mysql-8.0-shell
tar -zxvf mysql-shell-8.0.13-linux-glibc2.12-x86-64bit.tar.gz -C /opt/mysql-8.0-shell && cd /opt/mysql-8.0-shell/mysql-shell-8.0.13-linux-glibc2.12-x86-64bit && mv * .. && ln -s /opt/mysql-8.0-shell/ /usr/local/mysqlshell

#加入環境變量並使其生效
echo  'export PATH=/usr/local/mysqlshell/bin/:$PATH' >>/etc/profile
source /etc/profile

4.3 使用mysql-shell創建MySQL innodb cluster

mysqlshell登錄PRIMARY節點

mysqlsh --uri root@127.0.0.1:3306

用已有的MGR創建innodb cluster

 MySQL  127.0.0.1:3306 ssl  JS > var fandercluster = dba.createCluster('fandercluster')
You are connected to an instance that belongs to an unmanaged replication group.
Do you want to setup an InnoDB cluster based on this replication group? [Y/n]: y
A new InnoDB cluster will be created based on the existing replication group on instance 'root@127.0.0.1:3306'.

Creating InnoDB cluster 'fandercluster' on 'root@127.0.0.1:3306'...
Adding Seed Instance...
Adding Instance '192-168-199-122:3306'...
Adding Instance '192-168-199-123:3306'...

Cluster successfully created based on existing replication group.

查看innodb cluster狀況

 MySQL  127.0.0.1:3306 ssl  JS > fandercluster.status()
{
    "clusterName": "fandercluster", 
    "defaultReplicaSet": {
        "name": "default", 
        "primary": "192-168-199-121:3306", 
        "ssl": "DISABLED", 
        "status": "OK", 
        "statusText": "Cluster is ONLINE and can tolerate up to ONE failure.", 
        "topology": {
            "192-168-199-121:3306": {
                "address": "192-168-199-121:3306", 
                "mode": "R/W", 
                "readReplicas": {}, 
                "role": "HA", 
                "status": "ONLINE"
            }, 
            "192-168-199-122:3306": {
                "address": "192-168-199-122:3306", 
                "mode": "R/O", 
                "readReplicas": {}, 
                "role": "HA", 
                "status": "ONLINE"
            }, 
            "192-168-199-123:3306": {
                "address": "192-168-199-123:3306", 
                "mode": "R/O", 
                "readReplicas": {}, 
                "role": "HA", 
                "status": "ONLINE"
            }
        }
    }, 
    "groupInformationSourceMember": "mysql://root@127.0.0.1:3306"
}

可以看出121是R/W模式,是PRIMARY節點。122和123是R/O模式,是SECONDARY節點。MGR狀態良好。
這樣,MySQL innodb cluster就部署好了。

4.4 MySQL Router部署

MySQL路由器實際上是InnoDB Cluster的一部分,是輕量級中間件,可在應用程序和后端MySQL服務器之間提供透明路由。它可用於各種用例,例如通過有效地將數據庫流量路由到適當的后端MySQL服務器來提供高可用性和可伸縮性。

有多少台應用服務器就要部署多少個mysql-router,這是官方推薦的架構。我們只有一台應用服務器192.168.199.198,我們部署一個mysql-router。

#下載mysql-router二進制安裝包
wget https://dev.mysql.com/get/Downloads/MySQL-Router/mysql-router-8.0.13-linux-glibc2.12-x86_64.tar.xz
mkdir -p /opt/mysql-8.0-router
tar -Jxvf mysql-router-8.0.13-linux-glibc2.12-x86_64.tar.xz -C /opt/mysql-8.0-router && cd /opt/mysql-8.0-router/mysql-router-8.0.13-linux-glibc2.12-x86_64 && mv * .. && ln -s /opt/mysql-8.0-router/ /usr/local/mysqlrouter

#加入環境變量並使其生效
echo  'export PATH=/usr/local/mysqlrouter/bin/:$PATH' >>/etc/profile
source /etc/profile

初始化mysql-router

#IP地址填PRIMARY節點即可

[root@localhost ~]# mysqlrouter --bootstrap root@192.168.199.121:3306 --user=root
Please enter MySQL password for root: 

Bootstrapping system MySQL Router instance...
Checking for old Router accounts
Creating account mysql_router1_klh7m3xmmru0@'%'
MySQL Router  has now been configured for the InnoDB cluster 'fandercluster'.

The following connection information can be used to connect to the cluster after MySQL Router has been started with generated configuration..

Classic MySQL protocol connections to cluster 'fandercluster':
- Read/Write Connections: localhost:6446
- Read/Only Connections: localhost:6447
X protocol connections to cluster 'fandercluster':
- Read/Write Connections: localhost:64460
- Read/Only Connections: localhost:64470

初始化后mysql-router自動生成一個默認的配置文件,在安裝路徑

[root@localhost mysqlrouter]# pwd
/usr/local/mysqlrouter
[root@localhost mysqlrouter]# ll mysqlrouter.conf 
-rw------- 1 root root 1222 Nov 30 14:34 mysqlrouter.conf

我們稍微修改一下配置文件
vi mysqlrouter.conf

# File automatically generated during MySQL Router bootstrap
[DEFAULT]
name=system
user=root
keyring_path=/opt/mysql-8.0-router/data/keyring
master_key_path=/opt/mysql-8.0-router/bin/.././mysqlrouter.key
connect_timeout=30
read_timeout=30

[logger]
level = INFO

[metadata_cache:fandercluster]
router_id=1
bootstrap_server_addresses=mysql://192-168-199-122:3306,mysql://192-168-199-123:3306,mysql://192-168-199-121:3306
user=mysql_router1_klh7m3xmmru0
metadata_cluster=fandercluster
ttl=0.5

[routing:fandercluster_default_rw]
bind_address=0.0.0.0
bind_port=6446
destinations=metadata-cache://fandercluster/default?role=PRIMARY
routing_strategy=round-robin
protocol=classic

[routing:fandercluster_default_ro]
bind_address=0.0.0.0
bind_port=6447
destinations=metadata-cache://fandercluster/default?role=SECONDARY
#routing_strategy=round-robin
routing_strategy=round-robin-with-fallback
protocol=classic

[routing:fandercluster_default_x_rw]
bind_address=0.0.0.0
bind_port=64460
destinations=metadata-cache://fandercluster/default?role=PRIMARY
routing_strategy=round-robin
protocol=x

[routing:fandercluster_default_x_ro]
bind_address=0.0.0.0
bind_port=64470
destinations=metadata-cache://fandercluster/default?role=SECONDARY
routing_strategy=round-robin
protocol=x

注釋的地方即為我修改的地方。可以看出配置文件配置了PRIMARY節點是讀寫模式的,SECONDARY是只讀模式。

[routing:fandercluster_default_ro]
bind_address=0.0.0.0
bind_port=6447
destinations=metadata-cache://fandercluster/default?role=SECONDARY
#routing_strategy=round-robin
routing_strategy=round-robin-with-fallback
protocol=classic

在這里,routing_strategy=round-robin,讀請求是在122、123兩個只讀服務器上輪訓的。但123服務器掛了后,依然會在122和123輪訓,這個用戶體驗就很差了,因為此時訪問123會報錯。而且當122、123兩個數據庫都掛的情況下,只讀請求無法打回到121上。而routing_strategy=round-robin-with-fallback算法解決上面的問題。

啟動mysqlrouter

mysqlrouter &

這樣,我們就部署好mysql router了,注意mysql router的路由模式是port base的,它提供了一個寫端口和一個讀端口來實現讀寫分離。

5.MySQL innodb cluster讀寫分離測試

5.1 測試寫端口

[root@localhost mysqlrouter]# for ((i=0;i<=5;i++));do mysql -uroot -proot -P6446 -h127.0.0.1 -e "select @@server_id";done;
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         121 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         121 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         121 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         121 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         121 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         121 |
+-------------+

測試符合預期

5.2測試讀端口

[root@localhost mysqlrouter]# for ((i=0;i<=5;i++));do mysql -uroot -proot -P6447 -h127.0.0.1 -e "select @@server_id";done; 
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         122 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         123 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         122 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         123 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         122 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         123 |
+-------------+

讀端口在兩台SECONDARY節點上輪訓,符合預期

5.3模擬SECONDARY節點掛了一台,讀路由情況

[root@192-168-199-123 ~]# service mysqld stop
Shutting down MySQL............. SUCCESS! 
[root@localhost mysqlrouter]# for ((i=0;i<=5;i++));do mysql -uroot -proot -P6447 -h127.0.0.1 -e "select @@server_id";done;
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         122 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         122 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         122 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         122 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         122 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         122 |
+-------------+

123服務器掛了,讀端口只路由到122服務上,測試符合預期。

5.4模擬SECONDARY節點兩台都掛了

[root@192-168-199-122 ~]# service mysqld stop
Shutting down MySQL............. SUCCESS! 
[root@192-168-199-123 ~]# service mysqld stop
Shutting down MySQL............. SUCCESS! 
[root@localhost mysqlrouter]# for ((i=0;i<=5;i++));do mysql -uroot -proot -P6447 -h127.0.0.1 -e "select @@server_id";done;
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         121 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         121 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         121 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         121 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         121 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         121 |
+-------------+

所有SECONDARY服務器掛了,讀端口路由到PRIMARY節點服務器121上,測試符合預期。(上面提到的round-robin-with-fallback算法)

5.5模擬PRIMARY-SECONDARY切換了,現在122是PRIMARY節點了,其他為SECONDARY節點。

mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-----------------+-------------+--------------+-------------+----------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST     | MEMBER_PORT | MEMBER_STATE | MEMBER_ROLE | MEMBER_VERSION |
+---------------------------+--------------------------------------+-----------------+-------------+--------------+-------------+----------------+
| group_replication_applier | 1e24f619-f44f-11e8-a0ec-000c29cde11e | 192-168-199-122 |        3306 | ONLINE       | PRIMARY     | 8.0.13         |
| group_replication_applier | 26602f27-f44f-11e8-a732-000c290c24bc | 192-168-199-123 |        3306 | ONLINE       | SECONDARY   | 8.0.13         |
| group_replication_applier | b0b6f17f-f44e-11e8-b0e2-000c2983982f | 192-168-199-121 |        3306 | ONLINE       | SECONDARY   | 8.0.12         |
+---------------------------+--------------------------------------+-----------------+-------------+--------------+-------------+----------------+
3 rows in set (0.00 sec)
[root@localhost mysqlrouter]# for ((i=0;i<=5;i++));do mysql -uroot -proot -P6446 -h127.0.0.1 -e "select @@server_id";done;
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         122 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         122 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         122 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         122 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         122 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         122 |
+-------------+
[root@localhost mysqlrouter]# for ((i=0;i<=5;i++));do mysql -uroot -proot -P6447 -h127.0.0.1 -e "select @@server_id";done;
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         123 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         121 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         123 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         121 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         123 |
+-------------+
mysql: [Warning] Using a password on the command line interface can be insecure.
+-------------+
| @@server_id |
+-------------+
|         121 |
+-------------+

寫端口路由到PRIMARY服務器122上,讀端口路由到SECONDARY服務器121和123上,測試符合預期。

6.Troubleshoot

6.1 組復制無法online,復制報2061錯誤

參考這里

#原因是沒有使用SSL時,你創建復制密碼時要指明mysql_native_password
CREATE USER rpl_user@'%' IDENTIFIED WITH 'mysql_native_password' BY 'password';

6.2 mysqlrouter初始化時報1044 mysql error

[root@localhost mysqlrouter]# mysqlrouter --bootstrap root@192.168.199.121:3306 --user=root
Please enter MySQL password for root: 

Bootstrapping system MySQL Router instance...
Checking for old Router accounts
Creating account mysql_router1_xi3qiedz3zuw@'%'
Executing statements failed with: 'Error creating MySQL account for router: Error executing MySQL query: Access denied for user 'root'@'%' to database 'mysql_innodb_cluster_metadata' (1044)' (1044), trying to connect to another node
Error: Error creating MySQL account for router: Error executing MySQL query: Access denied for user 'root'@'%' to database 'mysql_innodb_cluster_metadata' (1044)


Error: It appears that a router instance named 'system' has been previously configured in this host. If that instance no longer exists, use the --force option to overwrite it.

解決: 初始化時--user=root這個用戶必須要有授權權限(with grant option)

GRANT ALL on *.* to root@'%' with grant option;

7.總結

MGR架構可以實現高可用,但實現failover,則需要安裝InnoDB Cluster了。MySQL shell和MySQL Router是InnoDB Cluster集群的一部分。MySQL shell用於安裝和管理InnoDB Cluster集群,InnoDB Cluster集群通過新建的原數據庫MySQL_innodb_cluster_metadata管理MGR集群狀態,MySQL Router通過周期性的訪問Cluster創建的MySQL_innodb_cluster_metadata庫中的元數據獲取集群成員信息,再通過performance_schema的系統表獲取可連接實例及其狀態來實現failover和讀負載均衡、讀寫分離的路由。
MySQL Router非常輕量級,性能損耗小於1%,官方建議每台應用上部署一個mysqlrouter節點,優點是節省網絡帶寬。缺點是mysqlrouter太輕量級了,只能提供簡單的基於端口的讀寫路由(Port based routing)和基於權重輪詢的負載均衡(Weighted Balance),不支持基於SQL的讀寫分離(Query based routing)和空閑優先的負載均衡(Application Layer balancer)。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM