(高可用)四、MySQL

一、主从复制

  • https://dev.mysql.com/doc/refman/5.7/en/replication-howto.html

  • slave向master认证

  • master向slave发送二进制日志

  • slave端IO线程将master发送来的日志写入本地,slave端SQL线程用于变更本地数据库

  • 影响IO线程正常工作的原因:

    1. master端防火墙
    1. 执行CHANGE MASTER时的信息在master端是否可用?
  • 影响SQL线程正常工作的原因:

    1. 原本的主从数据不一致
  • slave端SQL线程单线程写入,相比IO线程较慢,怎么解决?

  • slave端IO线程是异步处理的,怎么解决同步问题?

1.打开GTID功能

  • https://dev.mysql.com/doc/refman/5.7/en/replication-gtids.html
  • 这样每次重启机器后,slave不需要再知道具体的master的日志id
  • gtid会自动增加,slave端根据gtid来进行同步
  • slave自动找拥有最近gtid的主机作为master
# master端
[mysqld]
basedir=/usr/local/mysql
datadir=/data/mysql
socket=/data/mysql/mysql.sock

log-bin=mysql-bin
server-id=1

gtid_mode=ON
enforce-gtid-consistency=ON


# slave端
[mysqld]
basedir=/usr/local/mysql
datadir=/data/mysql
socket=/data/mysql/mysql.sock

server-id=2
gtid_mode=ON
enforce-gtid-consistency=ON


# 重启mysql,先起master

2.半同步模式

  • https://dev.mysql.com/doc/refman/5.7/en/replication-semisync.html
  • 无损模式
# master端
INSTALL PLUGIN rpl_semi_sync_master SONAME 'semisync_master.so';

# slave端
INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so';

# 查看激活状态
mysql> SELECT PLUGIN_NAME, PLUGIN_STATUS
    ->        FROM INFORMATION_SCHEMA.PLUGINS
    ->        WHERE PLUGIN_NAME LIKE '%semi%';
+---------------------+---------------+
| PLUGIN_NAME         | PLUGIN_STATUS |
+---------------------+---------------+
| rpl_semi_sync_slave | ACTIVE        |
+---------------------+---------------+
1 row in set (0.00 sec)

# 打开半同步功能(热激活)
## master端
SET GLOBAL rpl_semi_sync_master_enabled = 1;

## slave端
SET GLOBAL rpl_semi_sync_slave_enabled = 1;

# 查看半同步变量
mysql> show variables like 'rpl_semi_sync%';
+-------------------------------------------+------------+
| Variable_name                             | Value      |
+-------------------------------------------+------------+
| rpl_semi_sync_master_enabled              | ON         |
| rpl_semi_sync_master_timeout              | 10000      |
| rpl_semi_sync_master_trace_level          | 32         |
| rpl_semi_sync_master_wait_for_slave_count | 1          |
| rpl_semi_sync_master_wait_no_slave        | ON         |
| rpl_semi_sync_master_wait_point           | AFTER_SYNC |
+-------------------------------------------+------------+
6 rows in set (0.01 sec)

# 查看半同步状态
mysql> show status like 'rpl_semi_sync%';
+--------------------------------------------+-------+
| Variable_name                              | Value |
+--------------------------------------------+-------+
| Rpl_semi_sync_master_clients               | 0     |
| Rpl_semi_sync_master_net_avg_wait_time     | 0     |
| Rpl_semi_sync_master_net_wait_time         | 0     |
| Rpl_semi_sync_master_net_waits             | 0     |
| Rpl_semi_sync_master_no_times              | 0     |
| Rpl_semi_sync_master_no_tx                 | 0     |
| Rpl_semi_sync_master_status                | ON    |
| Rpl_semi_sync_master_timefunc_failures     | 0     |
| Rpl_semi_sync_master_tx_avg_wait_time      | 0     |
| Rpl_semi_sync_master_tx_wait_time          | 0     |
| Rpl_semi_sync_master_tx_waits              | 0     |
| Rpl_semi_sync_master_wait_pos_backtraverse | 0     |
| Rpl_semi_sync_master_wait_sessions         | 0     |
| Rpl_semi_sync_master_yes_tx                | 0     |
+--------------------------------------------+-------+
14 rows in set (0.00 sec)

# 重启slave端的IO线程
mysql> STOP SLAVE IO_THREAD;
Query OK, 0 rows affected (0.00 sec)

mysql> START SLAVE IO_THREAD;
Query OK, 0 rows affected (0.01 sec)

mysql>  show status like 'rpl_semi_sync%';
+----------------------------+-------+
| Variable_name              | Value |
+----------------------------+-------+
| Rpl_semi_sync_slave_status | ON    |
+----------------------------+-------+
1 row in set (0.01 sec)

# 如果slave端的IO线程挂掉,master端会等待一个超时时间后,切换成异步工作状态

3.延迟复制

mysql> stop slave SQL_THREAD;
Query OK, 0 rows affected (0.00 sec)

mysql> change master to master_delay=10;
Query OK, 0 rows affected (0.00 sec)

mysql> start slave SQL_THREAD;

4.慢查询

mysql> set global slow_query_log=ON;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like "long%";
+-----------------+-----------+
| Variable_name   | Value     |
+-----------------+-----------+
| long_query_time | 10.000000 |
+-----------------+-----------+
1 row in set (0.00 sec)

mysql> set long_query_time=5;
Query OK, 0 rows affected (0.00 sec)

mysql> show variables like "long%";
+-----------------+----------+
| Variable_name   | Value    |
+-----------------+----------+
| long_query_time | 5.000000 |
+-----------------+----------+
1 row in set (0.00 sec)

5.并行SQL写入

  • 加速slave端的SQL线程写入
# slave端修改配置文件
[mysqld]
basedir=/usr/local/mysql
datadir=/data/mysql
socket=/data/mysql/mysql.sock

server-id=2
gtid_mode=ON
enforce-gtid-consistency=ON

slave-parallel-type=LOGICAL_CLOCK
slave-parallel-workers=16
master_info_repository=TABLE
relay_log_info_repository=TABLE
relay_log_recovery=ON


# 查看slave端的线程
mysql> show processlist;
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
| Id | User        | Host      | db   | Command | Time | State                                                  | Info             |
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
|  1 | system user |           | NULL | Connect |   53 | Slave has read all relay log; waiting for more updates | NULL             |
|  3 | system user |           | NULL | Connect |   53 | Waiting for master to send event                       | NULL             |
|  4 | system user |           | NULL | Connect |   53 | Waiting for an event from Coordinator                  | NULL             |
|  5 | system user |           | NULL | Connect |   53 | Waiting for an event from Coordinator                  | NULL             |
|  6 | system user |           | NULL | Connect |   53 | Waiting for an event from Coordinator                  | NULL             |
|  7 | system user |           | NULL | Connect |   53 | Waiting for an event from Coordinator                  | NULL             |
|  8 | system user |           | NULL | Connect |   53 | Waiting for an event from Coordinator                  | NULL             |
|  9 | system user |           | NULL | Connect |   53 | Waiting for an event from Coordinator                  | NULL             |
| 10 | system user |           | NULL | Connect |   53 | Waiting for an event from Coordinator                  | NULL             |
| 11 | system user |           | NULL | Connect |   53 | Waiting for an event from Coordinator                  | NULL             |
| 12 | system user |           | NULL | Connect |   53 | Waiting for an event from Coordinator                  | NULL             |
| 13 | system user |           | NULL | Connect |   53 | Waiting for an event from Coordinator                  | NULL             |
| 14 | system user |           | NULL | Connect |   53 | Waiting for an event from Coordinator                  | NULL             |
| 15 | system user |           | NULL | Connect |   53 | Waiting for an event from Coordinator                  | NULL             |
| 16 | system user |           | NULL | Connect |   53 | Waiting for an event from Coordinator                  | NULL             |
| 17 | system user |           | NULL | Connect |   53 | Waiting for an event from Coordinator                  | NULL             |
| 18 | system user |           | NULL | Connect |   53 | Waiting for an event from Coordinator                  | NULL             |
| 19 | system user |           | NULL | Connect |   53 | Waiting for an event from Coordinator                  | NULL             |
| 20 | root        | localhost | NULL | Query   |    0 | starting                                               | show processlist |
+----+-------------+-----------+------+---------+------+--------------------------------------------------------+------------------+
19 rows in set (0.00 sec)

二、组复制

  • https://dev.mysql.com/doc/refman/5.7/en/group-replication.html
  • 仅支持innodb
  • 最多支持9个节点为一组
  • 每个节点既是主又是从
  • 所有节点之间同步,如果一个节点出现故障,则全部回滚
  • 组复制需要保证节点之间的原始数据完全相同

第一个节点配置

# 关闭mysqld,清除原data
[root@localhost ~]# /etc/init.d/mysqld stop
[root@localhost ~]# rm -rf /data/mysql/*
[root@localhost ~]# ll /data/mysql/
total 0

# 修改my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/data/mysql
socket=/data/mysql/mysql.sock

disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY"
server_id=1
gtid_mode=ON
enforce_gtid_consistency=ON
master_info_repository=TABLE
relay_log_info_repository=TABLE
binlog_checksum=NONE
log_slave_updates=ON
log_bin=binlog
binlog_format=ROW

plugin_load_add='group_replication.so'
transaction_write_set_extraction=XXHASH64
group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"
group_replication_start_on_boot=off
group_replication_local_address= "server1:33061"
group_replication_group_seeds= "server1:33061,server2:33061,server3:33061"
group_replication_bootstrap_group=off
group_replication_single_primary_mode=OFF
group_replication_enforce_update_everywhere_checks=ON
group_replication_ip_whitelist="192.168.147.0/24,127.0.0.1/8"
group_replication_allow_local_disjoint_gtids_join=1


# 重新初始化mysql
[root@localhost ~]# mysqld --initialize --user=mysql

# 进入mysql修改root密码
[root@localhost ~]# /etc/init.d/mysqld start
Starting MySQL.Logging to '/data/mysql/server1.err'.
 SUCCESS!
[root@localhost ~]# mysql -uroot -p
Enter password:
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.36-log

Copyright (c) 2000, 2021, Oracle and/or its affiliates.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> alter user root@localhost identified by 'passwd';
Query OK, 0 rows affected (0.00 sec)


# 创建用于组复制的用户,在此期间关闭二进制日志记录
mysql> SET SQL_LOG_BIN=0;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'password';
Query OK, 0 rows affected (0.00 sec)

mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
Query OK, 0 rows affected (0.00 sec)

mysql> SET SQL_LOG_BIN=1;
Query OK, 0 rows affected (0.00 sec)


# 激活组复制,在初始节点激活组复制时需要开启bootstrap,其他节点不用
mysql> CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='password' FOR CHANNEL 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.03 sec)

mysql> SET GLOBAL group_replication_bootstrap_group=ON;
Query OK, 0 rows affected (0.00 sec)

mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected, 1 warning (2.09 sec)

mysql> SET GLOBAL group_replication_bootstrap_group=OFF;
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 1ddadb97-93f0-11ed-9d79-000c299c98e4 | server1     |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
1 row in set (0.00 sec)

其他节点配置

  • 只需要注意修改my.cnf中的部分内容
  • 在创建rpl_user需要暂时关闭二进制日志写入(防止数据不一致)
  • 开启组复制功能时,不需要再开启bootstrap功能
mysql> SET SQL_LOG_BIN=0;
Query OK, 0 rows affected (0.00 sec)

mysql> CREATE USER rpl_user@'%' IDENTIFIED BY 'password';
Query OK, 0 rows affected (0.01 sec)

mysql> GRANT REPLICATION SLAVE ON *.* TO rpl_user@'%';
Query OK, 0 rows affected (0.00 sec)

mysql> SET SQL_LOG_BIN=1;
Query OK, 0 rows affected (0.00 sec)

mysql> CHANGE MASTER TO MASTER_USER='rpl_user', MASTER_PASSWORD='password' FOR CHANNEL 'group_replication_recovery';
Query OK, 0 rows affected, 2 warnings (0.01 sec)

mysql> START GROUP_REPLICATION;
Query OK, 0 rows affected, 1 warning (3.28 sec)

实验效果

# 可以看到各环节都是online状态
mysql> SELECT * FROM performance_schema.replication_group_members;
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| CHANNEL_NAME              | MEMBER_ID                            | MEMBER_HOST | MEMBER_PORT | MEMBER_STATE |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
| group_replication_applier | 1ddadb97-93f0-11ed-9d79-000c299c98e4 | server1     |        3306 | ONLINE       |
| group_replication_applier | 52d2a816-93f2-11ed-ad4b-000c29ad4e3c | server3     |        3306 | ONLINE       |
| group_replication_applier | de36bbfc-93f0-11ed-905c-000c29f090f3 | server2     |        3306 | ONLINE       |
+---------------------------+--------------------------------------+-------------+-------------+--------------+
3 rows in set (0.00 sec)

# 此时在任意一个节点插入数据,都会被同步到其他节点

三、读写分离

  • 使用包mysql-router
  • 下载地址:https://cdn.mysql.com/archives/mysql-router/mysql-router-community-8.0.21-1.el7.x86_64.rpm
  • 配置文件:/etc/mysqlrouter
[routing:ro]  # 配置读路由策略
bind_address=0.0.0.0 
bind_port=7001
destinations=192.168.147.138:3306,192.168.147.139:3306,192.168.147.140:3306
routing_strategy=round-robin  # 轮询

[routing:rw]  # 配置写路由策略
bind_address=0.0.0.0
bind_port=7002
destinations=192.168.147.138:3306,192.168.147.139:3306,192.168.147.140:3306
routing_strategy=round-first-available  # 首位可用
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值