一、MySQL集群概述

1. 集群的主要类型

  • 高可用集群(High Available Cluster,HA)
  • 高可用集群是指通过特殊的软件把独立的服务器连接起来,组成一个能够提供故障切换(Fail Over)功能的集群

2. 如何衡量高可用

可用性级别(指标)年度宕机时间描述叫法
99%3.65天/年基本可用系统2个9
99.9%8.76小时/年可用系统3个9
99.99%52.6分钟/年高可用系统4个9
99.999%5.3分钟/年抗故障系统5个9
99.9999%32秒/年容错系统6个9

计算方法:

1年 = 365天 = 8760小时
99% = 8760 * 1% = 8760 * 0.01 = 87.6小时=3.65天
99.9 = 8760 * 0.1% = 8760 * 0.001 = 8.76小时
99.99 = 8760 * 0.0001 = 0.876小时 = 0.876 * 60 = 52.6分钟
99.999 = 8760 * 0.00001 = 0.0876小时 = 0.0876 * 60 = 5.26分钟

3. 常用的集群架构

  • ==MySQL Replication==
  • MySQL Cluster
  • MySQL Group Replication (MGR) 5.7.17
  • MariaDB Galera Cluster
  • ==MHA==|Keepalived|HeartBeat|Lvs,Haproxy等技术构建高可用集群

二、MySQL复制简介

1. 什么是MySQL复制

  • Replication可以实现将数据从一台数据库服务器(master)复制到一台到多台数据库服务器(slave)
  • 默认情况下,属于异步复制,所以无需维持长连接

2. MySQL复制原理

简单来说,master将数据库的改变写入**==二进制日志==,slave同步这些二进制日志,并根据这些二进制日志进行==数据重演操作==**,实现数据异步同步。

详细描述:

  1. slave端的IO线程发送请求给master端的binlog dump线程
  2. master端binlog dump线程==获取二进制日志==信息(==文件名和位置信息==)发送给slave端的IO线程
  3. salve端IO线程获取到的内容==依次==写到slave端relay log里,并把master端的bin-log文件名和位置记录到master.info里
  4. salve端的SQL线程,检测到relay log中内容更新,就会解析relay log里更新的内容,并==执行这些操作==,从而达到和master数据一致

3. MySQL复制架构

3.1 双机热备(1主1从)

web_server >读写请求> mysql_master >复制>mysql_slave

默认情况下,master接受读写请求,slave只接受读请求以减轻master的压力。

3.2 级联复制 (1主多从)

web_server >读写请求> mysql_master >复制>mysql_slave >复制>mysql_slave

**优点:**进一步分担读压力

**缺点:**slave1 出现故障,后面的所有级联slave服务器都会同步失败

3.3 并联复制 (1主多从)

web_server >读写请求> mysql_master >复制>mysql_slave

​ >复制>mysql_slave

**优点:**解决上面的slave1的单点故障,同时也分担读压力

**缺点:**间接增加master的压力(传输二进制日志压力)

3.4 双主复制 (M-M)

web_server >读写请求> mysql_master1 >复制< mysql_master2

特点:

从命名来看,两台master好像都能接受读、写请求,但实际上,往往运作的过程中,同一时刻只有其中一台master会接受写请求,另外一台接受读请求。

三、MySQL复制搭建

1. 传统AB复制架构(M-S)

说明:当前环境中master上已有mysql数据库,版本为5.6.35

① 实现环境

mysql_master 192.168.2.115

mysql_slave 192.168.2.116

③ 搭建主从复制思路
  1. slave必须安装相同版本的mysql数据库软件
  2. master端必须开启二进制日志(binlog);slave端必须开启relay log日
  3. master端和slave端的server-id号必须不能一致
  4. slave端配置向master来同步数据
    • master端必须创建一个复制用户
    • 保证master和slave端初始数据一致
    • 配置主从复制(slave端)
④ 主从搭建步骤
⑴ Slave安装MySQL软件
#!/bin/bash
#判断创建mysql用户
id mysql
[ $? -eq 1 ] && useradd -rs /sbin/nologin mysql
mkdir -p /root/soft/
cd /root/soft/
#下载安装包
wget https://dev.mysql.com/get/Downloads/MySQL-5.6/mysql-5.6.35-linux-glibc2.5-x86_64.tar.gz
#解压
tar xf mysql-5.6.35-linux-glibc2.5-x86_64.tar.gz 
mv mysql-5.6.35-linux-glibc2.5-x86_64 /usr/local/mysql
#更改属主属组
chown -R mysql. /usr/local/mysql/
cp /usr/local/mysql/support-files/mysql.server /etc/init.d/mysql

#注意:
#暂时不需要初始化数据库文件,只是安装好了和master相同版本的mysql数据库软件;后面向master来同步所有数据。


⑵ 修改主从配置文件

注意:master和slave都要修改!

  • server-id必须不能一致;
  • master需要开启二进制日志
  • slave需要开启中继日志
[root@master ~]# cat /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
port=3307
socket=/usr/local/mysql/mysql.sock
log-error=/usr/local/mysql/data/db01_3307.err
character_set_server=utf8mb4
server-id = 10
#开启二进制日志
log-bin=/usr/local/mysql/data/binlog

[root@slave ~]# cat /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
socket=/usr/local/mysql/mysql.sock
log-error=/usr/local/mysql/data/db02_3307.err
character_set_server=utf8mb4
server-id=20
#开启中继日志
relay-log=/usr/local/mysql/data/relaylog
⑶ master上的数据复制到slave
  1. 停止master上的mysql服务
[root@master ~]# mysqladmin shutdown -p123
  1. ==删除auto.cnf文件==
[root@master data]# rm -f /usr/local/mysql/data/auto.cnf
说明:auto.cnf文件里保存的是每个数据库实例的UUID信息,代表数据库的唯一标识
  1. 同步master数据到slave
[root@master data]# rsync -av /usr/local/mysql/data/ 192.168.2.116:/usr/local/mysql/data
  1. 启动master和slave数据库
[root@master ~]# service mysql start
[root@slave ~]# service mysql start
⑷ slave配置向master同步数据
  1. master端创建授权用户
mysql>
grant replication slave on *.* to 'slave'@'10.1.1.%' identified by '123';
grant replication slave on *.* to 'slave'@'192.168.2.%'identified by '123';
#用户名:'slave'@'10.1.1.%'
#密码:123
mysql> flush privileges;
  1. 查看master上正在写的二进制文件名和位置
先加锁,防止两边数据不一致
mysql> flush tables with read lock;
查看当前数据库的二进制日志写到什么位置(只有打开二进制日志,这句命令才有结果)
mysql> show master status;
+-----------------+----------+--------------+------------------+----------
| File            | Position | Binlog_Do_DB | Binlog_Ignore_DB | Executed_Gtid_Set |
+-----------------+----------+--------------+------------------+----------------
| mybinlog.000002 |      405 |              |                  |               |
+-----------------+----------+--------------+------------------+----------
  1. slave上配置同步信息
mysql> change master to master_host='10.1.1.37',master_user='slave',master_password='123',master_port=3306,master_log_file='mybinlog.000004',master_log_pos=405;

说明:
master_host   		master的IP
master_user	  		复制的用户
master_password  	复制用户密码
master_port			master的端口号
master_log_file		master正在写的二进制文件名,锁表后查看的
master_log_pos    	master正在写的二进制位置
  1. 启动复制线程,开始同步
mysql> start slave;
mysql> show slave status\G;
				.....
            Slave_IO_Running: Yes 代表成功连接到master并且下载日志
            Slave_SQL_Running: Yes 代表成功执行日志中的SQL语句
启动slave报如下错误:
mysql> start slave;
ERROR 1872 (HY000): Slave failed to initialize relay log info structure from the repository
解决:删除relay-log.info,重启mysql服务或者mysql>reset slave;
  1. master上解锁
mysql> unlock tables;
Query OK, 0 rows affected (0.00 sec)
  1. 测试验证
master上插入数据:
mysql> select * from db02.t1;
mysql> insert into t1 values(4,'tom');
Query OK, 1 row affected (0.00 sec)

slave上查看数据:
mysql> select * from db02.t1;

⑤ 数据不一致导致同步失效

通过变量sql_slave_skip_counter临时跳过事务进行处理

SET GLOBAL sql_slave_skip_counter = N  	N代表跳过N个事务
举例说明:
mysql> SET GLOBAL sql_slave_skip_counter=1;
mysql> stop slave;
mysql> start slave;
注意:
1. 跳过事务应该在slave上进行
2. 传统的AB复制方式可以使用变量:sql_slave_skip_counter,基于GTIDs的方式不支持

2. 基于GTIDs的AB复制架构(M-S)

2.1 关于GTIDs概述
  1. GTIDs(Global transaction identifiers)全局事务标识符,是mysql 5.6新加入的一项技术

  2. 当使用GTIDs时,每一个事务都可以被识别并且跟踪

  3. 添加新的slave或者当发生故障需要将master身份或者角色迁移到slave上时,都无需考虑是哪一个二进制日志以及哪个position值,极大简化了相关操

  4. GTIDs是完全基于事务的,因此不支持MYISAM存储引擎

  5. GTIDs由source_id和transaction_id组成:

    1)source_id来自于server_uuid,可以在auto.cnf中看到

    2)transation_id是一个序列数字,自动生成.

  6. 在mysql 5.6.7之前,使用==mysql_upgrade==命令会出现问题

2.2 基于GTIDs的配置

利用已有的传统m-s环境升级至基于GITDs的Replication

  1. 为了保证数据一致性,master和slave设置为只读模式 (主+从)
  2. 修改配置文件支持GTIDs (主+从)
  3. 重启数据库 (主+从)
  4. ==从服务器上重新配置同步== (从)
① 主从设置只读模式
mysql> set @@global.read_only=ON;
② 修改配置文件支持GTIDs
[root@master ~]# cat /etc/my.cnf
[mysqld]
basedir=/usr/local/mysql
datadir=/usr/local/mysql/data
port=3307
socket=/usr/local/mysql/mysql.sock
log-error=/usr/local/mysql/data/db01_3307.err
character_set_server=utf8mb4
log-bin=/usr/local/mysql/data/binlog
server-id = 10
gtid-mode=on
log-slave-updates=1
enforce-gtid-consistency

[root@slave ~]# cat /etc/my.cnf
[mysqld]
basedir = /usr/local/mysql
datadir = /usr/local/mysql/data
socket=/usr/local/mysql/mysql.sock
log-error=/usr/local/mysql/data/db02_3307.err
log-bin=/usr/local/mysql/data/mybinlog   			#=>  这里一定要设置
character_set_server=utf8mb4
server-id = 20
relay-log = /usr/local/mysql/data/relaylog
log-slave-updates=1
gtid-mode=on
enforce-gtid-consistency=1
skip-slave-start

说明:
1)开启GITDs需要在master和slave上都配置gtid-mode,log-bin,log-slave-updates,enforce-gtid-consistency(该参数在5.6.9之前是--disable-gtid-unsafe-statement)
2)其次,slave还需要增加skip-slave-start参数,目的是启动的时候,先不要把slave起来,需要做一些配置
3)基于GTIDs复制从服务器必须开启二进制日志!
③ 重起主从数据库服务
[root@master ~]# service mysql restart
Starting MySQL.. SUCCESS!
[root@slave ~]# service mysql restart
Starting MySQL.. SUCCESS! 
④ slave重新配置同步(重要)
mysql> change master to master_host='192.168.2.115',master_user='slave',master_password='123',master_port=3307,master_auto_position=1;

注意:
1.确保有复制用户
2.主要区别于传统复制的参数是:master_auto_position=1
⑤ slave上启动同步线程
mysql> start slave;
⑥ 关闭只读模式
mysql> set @@global.read_only=OFF;
⑦ 测试验证
[root@master ~]# show master status;
Executed_Gtid_Set   有值时GITDs为已开
2.3 基于GTIDs手动跳过事务
指定需要跳过的GTIDs编号
SET GTID_NEXT='aaa-bbb-ccc-ddd:N';
开始一个空事务
BEGIN;
COMMIT;
使用下一个自动生成的全局事务ID。
SET GTID_NEXT='AUTOMATIC';

举例说明:
mysql> stop slave;
mysql> SET @@SESSION.GTID_NEXT= '044e6392-cf9b-11e8-a748-000c294ca304:3';
mysql> BEGIN;
mysql> commit;
mysql> SET @@SESSION.GTID_NEXT= 'AUTOMATIC';	
mysql> start slave;
mysql> show slave status\G

说明:需要跳过哪个事务,需要手动查看relaylog文件得到
[root@slave1 data]# ../bin/mysqlbinlog relay.000003|less
。。。。
# at 756
#181015 12:04:45 server id 10  end_log_pos 817 CRC32 0x5374f49e         GTID [commit=yes]
SET @@SESSION.GTID_NEXT= '044e6392-cf9b-11e8-a748-000c294ca304:3'/*!*/;