目录
MySQL集群是一个高性能、高可用性和可扩展的数据库解决方案,它利用分布式技术将数据存储在多个节点上,以实现负载均衡和故障容忍。下面我将从MySQL的源码部署,到实现MySQL集群的高可用一一来讲解。
本章的实验环境是基于三台虚拟机(基于红帽7),其IP分别为172.25.254.10,172.25.254.20,172.25.254.30
主机名分别为mysql1,mysql2,mysql3。
一、源码部署mysql
1.1 下载源码包
在这里我是使用的 mysql-boost-5.7.44.tar.gz,这个源码包,可以去官网去下载。
然后传到每台虚机上,并解压,再切换到目录里。
下载源码依赖包:
[root@mysql1 mysql-5.7.44]# yum install cmake gcc-c++ openssl-devel ncurses-devel.x86_64 libtirpc-devel-1.3.3-8.el9_4.x86_64.rpm rpcgen.x86_64
#下载cmake编译软件。
yum install cmake -y
1.2 安装部署
编译:
[root@mysql1 mysql-5.7.44]# cmake -DCMAKE_INSTALL_PREFIX=/usr/local/mysql -DMYSQL_DATADIR=/data/mysql -DMYSQL_UNIX_ADDR=/data/mysql/mysql.sock -DWITH_INNOBASE_STORAGE_ENGINE=1 -DWITH_EXTRA_CHARSETS=all -DDEFAULT_CHARSET=utf8mb4 -DDEFAULT_COLLATION=utf8mb4_unicode_ci -DWITH_BOOST=/root/mysql-5.7.44/boost/boost_1_59_0/
然后安装:
[root@mysql1 mysql-5.7.44]# make -j2 && make install
安装成功界面如下。
部署数据库:
#生成数据目录
useradd -s /sbin/nologin -M mysql mkdir /data/mysql -p chown mysql.mysql -R /data/mysql
#生成启动脚本
[root@mysql1 ~]# cd /usr/local/mysql/support-files/ [root@mysql1 support-files]# cp mysql.server /etc/init.d/mysqld
#修改环境变量
#修改环境变量 [root@mysql1 ~]# vim ~/.bash_profile export PATH=$PATH:/usr/local/mysql/bin [root@mysql1 ~]# source ~/.bash_profile
#修改配置文件
# 数据库初始化建立 mysql 基本数据,注意保存其密码mysqld --user mysql --initialize
#安全初始化,修改密码
mysql_secure_installation
#然后直接启动/etc/init.d/mysqld start#然后使用chkconfig来设定开机yum install chkconfig mysqld onchkconfig mysqld on
然后我们的安装部署就完成了,后面两台的配置和上面的一样。
二、mysql 的主从复制
2.1 在master上配置
修改配置文件,添加二进制日志。
然后重启:[root@mysql-node10 ~]# /etc/init.d/mysqld restart
就生成了/data/mysql
# 进入数据库配置用户权限##生成专门用来做复制的用户,此用户是用于slave端做认证用 mysql> CREATE USER 'repl'@'%' IDENTIFIED BY '123456'; Query OK, 0 rows affected (0.00 sec) mysql> GRANT REPLICATION SLAVE ON *.* TO repl@'%'; Query OK, 0 rows affected (0.01 sec)
2.2 在slave上的配置
首先修改配置文件添加server-id
[root@mysql2 ~]# vim /etc/my.cnf [mysqld] datadir=/data/mysql socket=/data/mysql/mysql.sock symbolic-links=0 server-id=20 [root@mysql2 ~]# vim /etc/my.cnf [mysqld] datadir=/data/mysql socket=/data/mysql/mysql.sock symbolic-links=0 server-id=30
#也是登录数据库
CHANGE MASTER TO MASTER_HOST='172.25.254.10',MASTER_USER='repl',MASTER_PASSWORD='123456',MASTER_LOG_FILE='mysql-bin.000001',MASTER_LOG_POS=595;
然后在从数据库里面start slave;
mysql> start slave;
查讯状态,能够看到20上面此时时slave;他的主是10;
2.3 测试
注意要在上面环境主从复制做完之后,再创建数据
然后在主上建数据库,表,从上可以看到
主10上面:
从20,30上面可以看到
2.4 延迟复制
在从20上面,添加延时![]()
然后在主上面添加一条数据
过了60秒后,从上面数据才会显示
2.5 慢查询日志
- 慢查询,顾名思义,执行很慢的查询
- 当执行SQL超过long_query_time参数设定的时间阈值(默认10s)时,就被认为是慢查询,这个SQL语句就是需要优化的
- 慢查询被记录在慢查询日志里
- 慢查询日志默认是不开启的
- 如果需要优化SQL语句,就可以开启这个功能,它可以让你很容易地知道哪些语句是需要优化的。
这个配置是在主上面完成的。
测试:
查看日志:
2.6 mysql的并行复制
# 在 slaves中设定,修改gtid,并添加配置![]()
[root@mysql2 ~]# vim /etc/my.cnf [mysqld] 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 #master信息在表中记录,默认记录 在/data/mysql//master.info relay_log_info_repository=TABLE #回放日志信息在表中记录,默认记录 在/data/mysql/relay-log.info relay_log_recovery=ON #日志回放恢复功能开启 [root@mysql2 ~]# /etc/init.d/mysql start Starting MySQL. SUCCESS!
测试查看:
此时 sql 线程转化为协调线程, 16 个 worker 负责处理 sql 协调线程发送过来的处理请求
注意:
2.7 原理剖析
三个线程实际上主从同步的原理就是基于 binlog 进行数据同步的。在主从复制过程中,会基于 3 个线程来操作, 一个主库线程,两个从库线程。
- 二进制日志转储线程(Binlog dump thread)是一个主库线程。当从库线程连接的时候, 主库可以将二进制日志发送给从库,当主库读取事件(Event)的时候,会在 Binlog 上加锁,读取完成之后,再将锁释放掉。
- 从库 I/O 线程会连接到主库,向主库发送请求更新 Binlog。这时从库的 I/O 线程就可以读取到主库的二进制日志转储线程发送的 Binlog 更新部分,并且拷贝到本地的中继日志 (Relay log)。
- 从库 SQL 线程会读取从库中的中继日志,并且执行日志中的事件,将从库中的数据与主库保持同步。
复制三步骤步骤 1 : Master 将写操作记录到二进制日志( binlog )。步骤 2 : Slave 将 Master 的 binary log events 拷贝到它的中继日志( relay log );步骤 3 : Slave 重做中继日志中的事件,将改变应用到自己的数据库中。 MySQL复制是异步的且串行化的,而且重启后从接入点开始复制。具体操作
- 1.slaves端中设置了master端的ip,用户,日志,和日志的Position,通过这些信息取得master的认证及 信息
- 2.master端在设定好binlog启动后会开启binlog dump的线程
- 3.master端的binlog dump把二进制的更新发送到slave端的
- 4.slave端开启两个线程,一个是I/O线程,一个是sql线程,
i/o线程用于接收master端的二进制日志,此线程会在本地打开relaylog中继日志,并且保存到本地 磁盘
- sql线程读取本地relog中继日志进行回放
- 5.什么时候我们需要多个slave?
当读取的而操作远远高与写操作时。我们采用一主多从架构
数据库外层接入负载均衡层并搭配高可用机制
2.8 架构缺陷
主从架构采用的是异步机制master 更新完成后直接发送二进制日志到 slave ,但是 slaves 是否真正保存了数据 master端不会检测master 端直接保存二进制日志到磁盘当 master 端到 slave 端的网络出现问题时或者 master 端直接挂掉,二进制日志可能根本没有到达slave master 出现问题 slave 端接管 master ,这个过程中数据就丢失了这样的问题出现就无法达到数据的强一致性,零数据丢失
三、半同步模式
3.1半同步模式原理
1. 用户线程写入完成后 master 中的 dump 会把日志推送到 slave 端2.slave 中的 io 线程接收后保存到 relaylog 中继日志3. 保存完成后 slave 向 master 端返回 ack4. 在未接受到 slave 的 ack 时 master 端时不做提交的,一直处于等待当收到 ack 后提交到存储引擎5. 在 5.6 版本中用到的时 after_commit 模式, after_commit 模式时先提交在等待 ack 返回后输出 ok
3.2 gtid模式
当为启用 gtid 时我们要考虑的问题
- 在master端的写入时多用户读写,在slave端的复制时单线程日志回放,所以slave端一定会延迟与master端
- 这种延迟在slave端的延迟可能会不一致,当master挂掉后slave接管,一般会挑选一个和master延迟日志最接近的充当新的master
- 那么为接管master的主机继续充当slave角色并会指向到新的master上,作为其slave
- 这时候按照之前的配置我们需要知道新的master上的pos的id,但是我们无法确定新的master和slave之间差多少
# 在主上面设置gtid模式
从20,30上面:
重启查看日志
# 开启 slave 端的 gtidCHANGE MASTER TO MASTER_HOST='172.25.254.10', MASTER_USER='repl', MASTER_PASSWORD='123456', MASTER_AUTO_POSITION=1;
3.3 启用半同步模式
在master端配置启用半同步模式
要在配置文件/etc/my.cnf 里面添加
rpl_semi_sync_master_enabled=1 # 开启半同步功能进入数据库安装插件在主上
然后再slave上面开启半同步:
要在配置文件/etc/my.cnf 里面添加
rpl_semi_sync_master_enabled=1 # 开启半同步功能Query OK, 0 rows affected (0.01 sec) mysql> SET GLOBAL rpl_semi_sync_slave_enabled =1; Query OK, 0 rows affected (0.00 sec) mysql> STOP SLAVE IO_THREAD; #重启io线程,半同步才能生效 Query OK, 0 rows affected (0.00 sec) mysql> START SLAVE IO_THREAD; ##重启io线程,半同步才能生效 Query OK, 0 rows affected (0.00 sec) mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%'; +---------------------------------+-------+ | Variable_name | Value | +---------------------------------+-------+ | rpl_semi_sync_slave_enabled | ON | | rpl_semi_sync_slave_trace_level | 32 | +---------------------------------+-------+ 2 rows in set (0.01 sec) mysql> SHOW STATUS LIKE 'Rpl_semi_sync%'; +----------------------------+-------+ | Variable_name | Value | +----------------------------+-------+ | Rpl_semi_sync_slave_status | ON | +----------------------------+-------+ 1 row in set (0.00 sec)
测试:
刚开始slave没有stop。添加数据非常快。
将slave上面stop,不会写入,
出现了10S超时,变成异步模式。
四、 mysql高可用之组复制 (MGR)
MySQL Group Replication( 简称 MGR ) 是 MySQL 官方于 2016 年 12 月推出的一个全新的高可用与高扩展的解决方案组复制是 MySQL 5.7.17 版本出现的新特性,它提供了高可用、高扩展、高可靠的 MySQL 集群服务 MySQL 组复制分单主模式和多主模式,传统的 mysql 复制技术仅解决了数据同步的问题,MGR 对属于同一组的服务器自动进行协调。对于要提交的事务,组成员必须就全局事务序列中给定事务 的顺序达成一致提交或回滚事务由每个服务器单独完成,但所有服务器都必须做出相同的决定如果存在网络分区,导致成员无法达成事先定义的分割策略,则在解决此问题之前系统不会继续进行, 这是一种内置的自动裂脑保护机制MGR 由组通信系统 ( Group Communication System , GCS ) 协议支持该系统提供故障检测机制、组成员服务以及安全且有序的消息传递
4.1 组复制流程
首先我们将多个节点共同组成一个复制组,在执行读写( RW)事务的时候,需要通过一致性协议层 ( Consensus 层)的同意,也就是读写事务想要进行提交,必须要经过组里 “ 大多数人 ” (对应 Node 节 点)的同意,大多数指的是同意的节点数量需要大于 ( N/2+1),这样才可以进行提交,而不是原发起 方一个说了算。而针对只读( RO )事务则不需要经过组内同意,直接 提交 即可Note节点数量不能超过 9 台
4.2 组复制单主和多主模式
single-primary mode( 单写或单主模式 )单写模式 group 内只有一台节点可写可读,其他节点只可以读。当主服务器失败时,会自动选择新的主服务器,
multi-primary mode( 多写或多主模式 )组内的所有机器都是 primary 节点,同时可以进行读写操作,并且数据是最终一致的。
4.3 部署 mysql组复制
注意:为了避免出错,在所有节点中重新生成数据库数据
注意要将半同步配置删了注意先将mysql关闭,再初始化
然后数据初始化,如果初始化有问题就将/data/mysql里的数据删了。
4.3.1 在主上面
修改/etc/my.cnf
[root@mysql-node10 ~]# vim /etc/my.cnf [mysqld] datadir=/data/mysql socket=/data/mysql/mysql.sock symbolic-links=0 server-id=1 #配置server唯一标识号 disabled_storage_engines="MyISAM,BLACKHOLE,FEDERATED,ARCHIVE,MEMORY" #禁用指定存储 引擎 gtid_mode=ON #启用全局事件标识 enforce_gtid_consistency=ON #强制gtid一致 master_info_repository=TABLE #复制事件数据到表中而不记录在数据目录中 relay_log_info_repository=TABLE binlog_checksum=NONE #禁止对二进制日志校验 log_slave_updates=ON #打开数据库中继, #当slave中sql线程读取日志后也会写入到自己的binlog中 log_bin=binlog #重新指定log名称 binlog_format=ROW #使用行日志格式 plugin_load_add='group_replication.so' #加载组复制插件 transaction_write_set_extraction=XXHASH64 #把每个事件编码为加密散列 group_replication_group_name="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa" #通知插件正 式加入 #或创建的组 名 #名称为 uuid格式 group_replication_start_on_boot=off #在server启动时不自动启动组复 制 group_replication_local_address="172.25.254.10:33061" #指定插件接受其他成员的信息端 口 group_replication_group_seeds="172.25.254.10:33061,172.25.254.20:33061, 172.25.254.30:33061" #本地地址允许访 问成员列表 group_replication_ip_whitelist="172.25.254.0/24,127.0.0.1/8" #主机白名单 #不随系统自启而启动,只在初始成员主机中手动开启, #需要在两种情况下做设定:1.初始化建组时 2.关闭并重新启动整个组时 group_replication_bootstrap_group=off group_replication_single_primary_mode=OFF #使用多主模式 group_replication_enforce_update_everywhere_checks=ON #组同步中有任何改变 检测更新 group_replication_allow_local_disjoint_gtids_join=1 #放弃自己信息以 master事件为主
然后初始化并修改密码
[root@mysql-node10 ~]# mysqld --user=mysql --initialize[root@mysql-node10 ~]# /etc/init.d/mysqld start[root@mysql-node10 ~]# mysql -uroot -p 初始化后生成的密码 -e "alter userroot@localhost identified by '123456';"#配置sql 注意此时要做本地解析,在三台主机里面。![]()
4.3.2 从上面
将配置文件里面id,ip修改了
再初始化,和上面一样的操作。
注意直接start
4.3.3 测试
写数据在主上建库,创表。从上插入数据,主上也可以查看
#在mysql-node10中 [root@mysql-node10 ~]# mysql -p mysql> CREATE DATABASE lee; Query OK, 1 row affected (0.00 sec) mysql> CREATE TABLE lee.userlist( -> username VARCHAR(10) PRIMARY KEY NOT NULL, -> password VARCHAR(50) NOT NULL -> ); Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO lee.userlist VALUES ('user1','111'); Query OK, 1 row affected (0.00 sec) mysql> SELECT * FROM lee.userlist; +----------+----------+ | username | password | +----------+----------+ | user1 | 111 | +----------+----------+ 1 row in set (0.00 sec) #在mysql-node20中 [root@mysql-node20 ~]# mysql -p mysql> INSERT INTO lee.userlist values ('user2','222'); Query OK, 1 row affected (0.00 sec) mysql> select * from lee.userlist; +----------+----------+ | username | password | +----------+----------+ | user1 | 111 | | user2 | 222 | +----------+----------+ 2 rows in set (0.00 sec) #mysql—node30中 [root@mysql-node30 ~]# mysql -p mysql> INSERT INTO lee.userlist values ('user3','333'); Query OK, 1 row affected (0.00 sec) mysql> select * from lee.userlist; +----------+----------+ | username | password | +----------+----------+ | user1 | 111 | | user2 | 222 | | user3 | 333 | +----------+----------+ 3 rows in set (0.00 sec)
五 mysql-router(mysql路由)
首先安装软件[root@mysql-router ~]# rpm -ivh mysql-router-community-8.4.0-1.el7.x86_64.rpm#修改配置文件,添加内容[root@mysql-router ~]# vim /etc/mysqlrouter/mysqlrouter.conf![]()
其他两台主机添加远程登录用户,两台上面都要添加20,30
10上面:登录并查询每次的id是否能够负载均衡
六、高可用之MHA--解决单点故障
6.1 MHA概述
什么是 MHA ?MHA ( Master High Availability )是一套优秀的 MySQL 高可用环境下故障切换和主从复制的软件。MHA 的出现就是解决 MySQL 单点的问题。MySQL 故障切换过程中, MHA 能做到 0-30 秒内自动完成故障切换操作。MHA 能在故障切换的过程中最大程度上保证数据的一致性,以达到真正意义上的高可用。MHA 的组成MHA 由两部分组成 :MHAManager ( 管理节点 ) MHA Node ( 数据库节点 ),MHA Manager 可以单独部署在一台独立的机器上管理多个 master-slave集群,也可以部署在一台slave 节点上。MHA Manager 会定时探测集群中的 master 节点。当 master 出现故障时,它可以自动将最新数据的 slave 提升为新的 master, 然后将所有其他的slave 重新指向新的 master 。MHA 的特点自动故障切换过程中, MHA 从宕机的主服务器上保存二进制日志,最大程度的保证数据不丢失使用半同步复制,可以大大降低数据丢失的风险,如果只有一个 slave已经收到了最新的二进制日 志, MHA 可以将最新的二进制日志应用于其他所有的 slave服务器上,因此可以保证所有节点的数据一致性目前 MHA 支持一主多从架构,最少三台服务,即一主两从故障切换备选主库的算法1 .一般判断从库的是从( position/GTID )判断优劣,数据有差异,最接近于 master 的 slave,成为备选 主。2 .数据一致的情况下,按照配置文件顺序,选择备选主库。3 .设定有权重( candidate_master=1 ),按照权重强制指定备选主。( 1 )默认情况下如果一个 slave 落后 master 100M 的 relay logs 的话,即使有权重,也会失效。( 2 )如果 check_repl_delay=0 的话,即使落后很多日志,也强制选择其为备选主。MHA 工作原理目前 MHA 主要支持一主多从的架构,要搭建 MHA, 要求一个复制集群必须最少有 3台数据库服务器, 一主二从,即一台充当 Master ,台充当备用 Master ,另一台充当从库。MHA Node 运行在每台 MySQL 服务器上MHAManager 会定时探测集群中的 master 节点当 master 出现故障时,它可以自动将最新数据的 slave 提升为新的 master然后将所有其他的 slave 重新指向新的 master , VIP 自动漂移到新的 master 。整个故障转移过程对应用程序完全透明。
6.2 MHA部署实施
环境需要再添加一个虚机来当作MHA服务器
解压
创建ssh公钥免密认证,让mha和后面几台进行免密认证
[root@mysql-mha ~]# ssh-keygen
[root@mysql-mha ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub root@172.25.254.10
[root@mysql-mha ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub root@172.25.254.20
[root@mysql-mha ~]# ssh-copy-id -i /root/.ssh/id_rsa.pub root@172.25.254.30
scp id_rsa root@172.25.254.10:/root/.ssh/
scp id_rsa root@172.25.254.20:/root/.ssh/
scp id_rsa root@172.25.254.30:/root/.ssh/
要写本地解析
一主两从:
还原配置,还原其他主机上的配置只剩下下面的。
然后停止数据库,三台都要停止 /etc/init.d/mysqld stop
要恢复成一主两从,初始化
启动半同步
10主上面:20上面当作备份master也要创建下面的repl
#打开半同步功能
mysql> SET GLOBAL rpl_semi_sync_master_enabled = 1;
#查看半同步功能状态
mysql> SHOW VARIABLES LIKE 'rpl_semi_sync%';
主的做完了,在从上面都要开启slave
mysql> CHANGE MASTER TO MASTER_HOST='172.25.254.10', MASTER_USER='repl', MASTER_PASSWORD='lee', MASTER_AUTO_POSITION=1; Query OK, 0 rows affected, 2 warnings (0.00 sec) mysql> start slave; Query OK, 0 rows affected (0.00 sec) mysql> INSTALL PLUGIN rpl_semi_sync_slave SONAME 'semisync_slave.so'; Query OK, 0 rows affected (0.01 sec) mysql> SET GLOBAL rpl_semi_sync_slave_enabled =1; Query OK, 0 rows affected (0.00 sec) mysql> STOP SLAVE IO_THREAD; Query OK, 0 rows affected (0.00 sec) mysql> START SLAVE IO_THREAD; Query OK, 0 rows affected (0.00 sec) mysql> SHOW STATUS LIKE 'Rpl_semi_sync%';
在mha上面安装软件包
将软件复制到在从上面
scp mha4mysql-node-0.58-0.el7.centos.noarch.rpm root@172.25.254.20:/root
scp mha4mysql-node-0.58-0.el7.centos.noarch.rpm root@172.25.254.30:/root
速度快一点修改下面的ssh配置文件
然后在三台虚拟主机上安装。
yum install mha4mysql-node-0.58-0.el7.centos.noarch.rpm -y
生成配置文件
mkdir /etc/masterha
解压mha4mysql-manager-0.58.tar.gz
tar zxf mha4mysql-manager-0.58.tar.gz
拷贝到下面/etc/masterha
先修改其他三个主机上的mysql权限。
并修改/etc/masterha/app1.cnf
测试:
检测网络及ssh免密
masterha_check_ssh --conf=/etc/masterha/app1.cnf
检测数据主从复制情况
注意要将每个MySQL主机里面开启bin-log日志功能
masterha_check_repl --conf=/etc/masterha/app1.cnf