MySQL集群高可用架构
MySQL主从架构
特点:成本低,布置快速,方便;读写分离;可以通过及时增加从库减少读库压力;主库单点故障;数据一致性问题
MySQL+DRDB架构
通过DRBD基于block块的复制模式,快速进行双主故障切换,很大程度上解决主库单点故障问题
架构特点:
1、高可用软件可使用Heartbeat,全面负责VIP、数据与DRBD服务的管理
2、主故障后可自动快速切换,并且从库仍然能通过VIP与新主库进行数据同步
3、从库也支持读写分离,可使用中间件或程序实现
MySQL+MHA架构
在mysql故障切换过程中,MHA能做到快速自动切换操作,而且还能最大限度保持数据的一致性
架构特点:
1、安装布署简单,不影响现有架构
2、自动监控和故障转移
3、保障数据一致性
4、故障切换方式可使用手动或自动多向选择
5、适应范围大(适用任何存储引擎)
MySQL+MMM架构
MMM即Master-Master Replication Manager for MySQL(mysql主主复制管理器),是关于mysql主主复制配置的监控、故障转移和管理的一套可伸缩的脚本套件
架构特点:
1、安全、稳定性较高,可扩展性好
2、 对服务器数量要求至少三台及以上
3、 对双主(主从复制性要求较高)
4、 同样可实现读写分离
主从复制
可以将主服务器(master)上的数据复制到从服务器(slave)上。
mysql支持的复制类型
1、基于语句(statement)的复制:在主服务器上执行SQL语句,在从服务器上执行同样的语句。MySQL默认采用基于语句的复制,效率比较高。
2、基于行(row)的复制:把改变的内容复制过去,而不是把命令在从服务器上执行一遍。从MySQL 5.0开始支持。
3、混合型(mixed)的复制:默认采用基于语句的复制,一旦发现基于语句的无法精确复制时,就会采用基于行的复制。
主从复制的作用
灾备
数据分布
负载平衡
读写分离
提高并发能力
主从复制原理
主要基于MySQL二进制日志
主要包括三个线程(2个I/O线程,1个SQL线程)
1、MySQL将数据变化记录到二进制日志中;
2、Slave将MySQL的二进制日志拷贝到Slave的中继日志中;
3、Slave将中继日志中的事件在做一次,将数据变化,反应到自身(Slave)的数据库
步骤:
1、主库开启bin_log日志并授权一个用户
2、检查是否授权一个用户
3、从库执行start slave(开启主从)
4、从库将主库的bin_log日志复制到自己的relay-log(中继日志)中
5、SQL线程从中继日志中取出上一次的之后的执行语句并执行
详细步骤:
1、从库通过执行change master to 语句连接主库,提供了连接的用户一切条件(user 、 password、port、ip),并且让从库知道,二进制日志的起点位置(file名 position 号); start slave
2、从库的IO线程和主库的dump线程建立连接。
3、从库根据change master to 语句提供的file名和position号,IO线程向主库发起binlog的请求。
4、主库dump线程根据从库的请求,将本地binlog以events的方式发给从库IO线程。
5、从库IO线程接收binlog events,并存放到本地relay-log中,传送过来的信息,会记录到 master.info中
6、从库SQL线程应用relay-log,并且把应用过的记录到relay-log.info中,默认情况下,已经应用过的 relay 会自动被清理purge
MySQL复制常用的拓扑结构
主从类型(Master-Slave)
主主类型(Master-Master)
级联类型(Master-Slave-Slave)A是B的主,B是C的主
主从复制的操作
主:master
从:slave 多实例:3306,3307
1、在从服务器上开启多实例
主服务器配置
1、开启binlog日志
[root@master ~]# vim /etc/my.cnf
log_bin=mysql-bin
server_id=1
2、进入数据库授权用户
[root@master ~]# mysql -uroot -p123456
mysql> grant replication slave on *.* to rep@'192.168.16.%' identified by '123456';
3、锁表
mysql> flush tables with read lock;
4、查看当前日志文件位置
mysql> show master status;
+------------------+----------+--------------+------------------+-------------------+
| File | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+------------------+----------+--------------+------------------+-------------------+
| mysql-bin.000003 | 447 | | | |
+------------------+----------+--------------+------------------+-------------------+
5、备份数据
[root@master mysql]# mysqldump -uroot -p123456 -A -B | gzip > /backup/mysql/mysql_bak.$(date +%F).sql.gz
mysqldump: [Warning] Using a password on the command line interface can be insecure.
6、解锁
mysql> unlock tables;
7、将数据复制到从库上
[root@master ~]# scp /backup/mysql/mysql_bak.2021-01-25.sql.gz 192.168.16.130:/tmp
root@192.168.16.130's password:
mysql_bak.2021-01-25.sql.gz 100% 204KB 1.1MB/s 00:00
从库上配置(多实例前提下)
1、开启服务
[root@slave ~]# mysqld_multi start 3306,3307
2、查看服务是否开启
[root@slave ~]# netstat -lnupt | grep 330
tcp6 0 0 :::3306 :::* LISTEN 16232/mysqld
tcp6 0 0 :::3307 :::* LISTEN 16400/mysqld
3、将复制过来的数据导入数据库
[root@slave ~]# zcat /tmp/mysql_bak.2021-01-25.sql.gz | mysql -uroot -p123456 -S /mysql/3306/mysql.sock
mysql: [Warning] Using a password on the command line interface can be insecure.
[root@slave ~]# zcat /tmp/mysql_bak.2021-01-25.sql.gz | mysql -uroot -p123456 -S /mysql/3307/mysql.sock
mysql: [Warning] Using a password on the command line interface can be insecure.
4、编辑配置文件
[root@slave ~]# mysql -uroot -p123456 -S /mysql/3306/mysql.sock
[root@slave ~]# mysql -uroot -p123456 -S /mysql/3307/mysql.sock
[root@slave ~]# vim /etc/my.cnf
[mysqld_multi]
mysqld = /usr/local/mysql/bin/mysqld_safe
mysqladmin = /usr/local/mysql/bin/mysqladmin
user = root
pass = 123456
[mysqld3306]
socket = /mysql/3306/mysql.sock
port = 3306
pid-file = /mysql/3306/mysql.pid
datadir = /mysql/3306/data
basedir = /usr/local/mysql
server_id=3306
[mysqld3307]
socket = /mysql/3307/mysql.sock
port = 3307
pid-file = /mysql/3307/mysql.pid
datadir = /mysql/3307/data
basedir = /usr/local/mysql
server_id=3307
5、重启服务
[root@slave ~]# mysqld_multi stop 3306,3307
[root@slave ~]# netstat -lnupt | grep 330
[root@slave ~]# mysqld_multi start 3306,3307
[root@slave ~]# netstat -lnupt | grep 330
tcp6 0 0 :::3306 :::* LISTEN 16918/mysqld
tcp6 0 0 :::3307 :::* LISTEN 16921/mysqld
6、进入3306数据库进行主从复制
[root@slave ~]# mysql -uroot -p123456 -S /mysql/3306/mysql.sock
mysql> change master to
-> master_host='192.168.16.128',
-> master_user='rep',
-> master_password='123456',
-> master_log_file='mysql-bin.000003',
-> master_log_pos=447;
[root@slave ~]# mysql -uroot -p123456 -S /mysql/3307/mysql.sock
mysql> change master to
-> master_host='192.168.16.128',
-> master_user='rep',
-> master_password='123456',
-> master_log_file='mysql-bin.000003',
-> master_log_pos=447;
7、开启主从复制
mysql> start slave;
8、查看主从状况监测主要参数
Slave_IO_Running: IO线程是否打开 YES/No/NULL
Slave_SQL_Running: SQL线程是否打开 YES/No/NULL
Seconds_Behind_Master: NULL #和主库比同步的延迟的秒数
主从复制出现错误
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Connecting to master
Master_Host: 192.168.16.128
Master_User: rep
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 154
Relay_Log_File: slave-relay-bin.000001
Relay_Log_Pos: 4
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Connecting 连接中
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 154
Relay_Log_Space: 154
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: NULL
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 2003
Last_IO_Error: error connecting to master '[email protected]:3306' - retry-time: 60 r
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 0
Master_UUID:
Master_Info_File: /mysql/3307/data/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp: 210126 09:23:41
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
从库上上测试能否访问主库服务器
[root@slave ~]# ping 192.168.16.128
PING 192.168.16.128 (192.168.16.128) 56(84) bytes of data.
64 bytes from 192.168.16.128: icmp_seq=1 ttl=64 time=0.710 ms
64 bytes from 192.168.16.128: icmp_seq=2 ttl=64 time=0.842 ms
出错原因:
没有关闭防火墙与Selinux
修正错误
主从库分别关闭防火墙和Selinux
[root@master ~]# systemctl stop firewalld.service
[root@master ~]# setenforce 0
[root@slave ~]# systemctl stop firewalld.service
[root@slave ~]# setenforce 0
重启主从复制
mysql> stop slave;
mysql> start slave;
查看
mysql> show slave status\G
*************************** 1. row ***************************
Slave_IO_State: Waiting for master to send event
Master_Host: 192.168.16.128
Master_User: rep
Master_Port: 3306
Connect_Retry: 60
Master_Log_File: mysql-bin.000003
Read_Master_Log_Pos: 447
Relay_Log_File: slave-relay-bin.000002
Relay_Log_Pos: 613
Relay_Master_Log_File: mysql-bin.000003
Slave_IO_Running: Yes
Slave_SQL_Running: Yes
Replicate_Do_DB:
Replicate_Ignore_DB:
Replicate_Do_Table:
Replicate_Ignore_Table:
Replicate_Wild_Do_Table:
Replicate_Wild_Ignore_Table:
Last_Errno: 0
Last_Error:
Skip_Counter: 0
Exec_Master_Log_Pos: 447
Relay_Log_Space: 820
Until_Condition: None
Until_Log_File:
Until_Log_Pos: 0
Master_SSL_Allowed: No
Master_SSL_CA_File:
Master_SSL_CA_Path:
Master_SSL_Cert:
Master_SSL_Cipher:
Master_SSL_Key:
Seconds_Behind_Master: 0
Master_SSL_Verify_Server_Cert: No
Last_IO_Errno: 0
Last_IO_Error:
Last_SQL_Errno: 0
Last_SQL_Error:
Replicate_Ignore_Server_Ids:
Master_Server_Id: 1
Master_UUID: a74aedab-554e-11eb-b297-000c296550da
Master_Info_File: /mysql/3307/data/master.info
SQL_Delay: 0
SQL_Remaining_Delay: NULL
Slave_SQL_Running_State: Slave has read all relay log; waiting for more updates
Master_Retry_Count: 86400
Master_Bind:
Last_IO_Error_Timestamp:
Last_SQL_Error_Timestamp:
Master_SSL_Crl:
Master_SSL_Crlpath:
Retrieved_Gtid_Set:
Executed_Gtid_Set:
Auto_Position: 0
Replicate_Rewrite_DB:
Channel_Name:
Master_TLS_Version:
9、测试
主库:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| school |
| sys |
+--------------------+
5 rows in set (0.10 sec)
mysql> create database xxx;
Query OK, 1 row affected (0.00 sec)
从库:3306
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| school |
| sys |
| xxx |
+--------------------+
3307
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| school |
| sys |
| xxx |
+--------------------+
6 rows in set (0.00 sec)
其他错误原因
主从时钟是否一致
网络通信是否存在延迟
是否和日志类型,数据过大有关 从库性能,
有没开启binlog 从库查询是否优化
常见状态错误排除
发现IO进程错误,检查日志,排除故障:# tail localhost.localdomain.err
错误一示例:
show slave status;
错误现象:
[ERROR] Slave I/O: Fatal error: The slave I/O thread stops because master and slave have equal MySQL server UUIDs; these UUIDs must be different for replication to work. Error_code: 1593
原因:从5.6开始复制引入了uuid的概念,各个复制结构中的server_uuid得保证不一样
解决方法:(从库是克隆机器) 修改从库的uuid
# vim auto.cnf
server-uuid=
错误二示例:
show slave status;
报错:Error xxx doesn’t exist
解决方法:
stop slave;
set global sql_slave_skip_counter = 1;
start slave;