目录
一、前言
二、mysql主从架构简介
2.1 mysql主从复制架构概述
2.2 为什么使用主从架构
2.2.1 提高数据可用性
2.2.2 提高数据可靠性
2.2.3 提升数据读写性能
2.3 主从架构原理
2.4 主从架构扩展
2.4.1 双机热备(AB复制)
2.4.2 级联复制
2.4.3 并联复制(一主多从)
三、搭建mysql主从
3.1 环境准备
3.2 搭建mysql主节点
3.2.1 配置yum源
3.2.2 安装mysql源
3.2.3 检查mysql源是否安装成功
3.2.4 安装mysql
3.2.5 启动mysql服务
3.2.5 mysql目录介绍
3.2.6 修改root账户密码
3.2.7 修改配置文件
3.3 搭建mysql从节点
3.4 主从节点配置
3.4.1 master配置
3.4.2 slave配置
3.5 创建同步账号
3.6 slave开启同步
3.7 测试与验证
四、搭建半同步复制
4.1 主从复制架构问题
4.2 什么是半同步复制
4.3 半同步复制搭建流程
4.3.1 前置准备
4.3.2 安装mysql插件
4.3.3 激活插件
4.3.4 slave节点重启IO线程
4.4 半同步复制效果测试
4.4.1 master插入一条数据
4.4.2 slave模拟发生故障
4.4.3 重新启动半同步复制
4.4.4 修改master等待时间
4.4.5 卸载半同步复制插件
4.4.6 补充说明
五、写在文末
mysql主从架构对很多同学来说并不陌生,mysql主从模式是很多集群架构的基础,基于mysql主从模式可以衍生出更复杂的集群架构,从而解决大规模甚至超大规模的数据问题,因此是每个学习者必须掌握的技能。但在实际业务中,单一的主从复制并不能很好的满足业务,因为mysql主从模式的数据同步是异步的,这就造成从节点可能会同步失败,于是就有了半同步复制模式。但是在开始学习半同步复制模式之前,让我们全面深入的了解下经典的mysql主从模式吧。
MySQL主从复制是指,将一个MySQL数据库数据同步到另一个MySQL数据库的过程。其中一个数据库是主库,另一个或多个数据库作为从数据库。主数据库负责写入和更新数据,而从数据库则复制主数据库的数据。
使用mysql主从架构,可以提高数据的可用性、可靠性和性能。
主从复制可以提高数据可用性。
如果主数据库出现故障,从数据库可以接管并提供服务,从而保障业务正常运行。主从复制还可以帮助实现数据备份和恢复,从而避免数据丢失和损坏。
主从复制可以提高数据可靠性。
当主数据库发生故障时,从数据库可以接管并提供服务,从而避免数据的丢失和损坏。主从复制还可以实现数据的近实时同步,从而避免数据的不一致性和错误。
主从复制可以提高数据性能。
当主数据库处理大量的并发请求时,可以通过配置读写分离的方式将一部分读请求分给从库,从而缓解主数据库压力,提高整个系统的性能。
简单来说,master将数据库的改变写入二进制日志,slave同步这些二进制日志,并根据这些二进制日志进行数据重演操作,实现数据异步同步。如下图所示为主从复制的过程。
结合上图,其详细的执行流程如下:
relay log :中继日志;
relay log 作用:记录从(slave)服务器接收来自主(master)服务器的二进制日志
由主从架构,结合实际业务,还可以扩展出更多的架构模式,下面列举几种由主从复制扩展出来的架构。
在这种模式下,master 接受读写请求,而slave只接受读请求以减轻master的压力。
即多个slave互相串联成一个链条的模式,后面的slave从前面的一个slave复制数据;
优点:可进一步分担读压力;
缺点:slave1(或中间某个slave) 出现故障,后面的所有级联slave服务器都会同步失败;
即一个master下面挂载多个slave节点;
特点:
从命名来看,两台master好像都能接受读、写请求,但实际上,往往运作的过程中,同一时刻只有其中一台master会接受写请求,另外一台接受读请求。
基于这种思想,如果想要实现多节点数据强一致性,业界也产生了其他成熟的解决方案,比如PXC集群模式,MGR集群模式,都属于多主模式,即多个节点均作为master同时对外提供读写服务。
本文使用云服务器,最低配置 2核2G,带宽4mb/s
编号 | IP地址 | 角色 | 操作系统 | 配置 |
---|---|---|---|---|
1 | 101.34.111.131 | 主节点(Master) | centos7.6 | 2核4G |
2 | 101.34.111.132 | 从节点(Slave) | centos7.6 | 2核2G |
下面基于rpm方式搭建,mysql版本为5.7,主从两个节点安装的过程基本相同,只在最后配置主从关系时有所不同,后面会重点说明,先演示在主节点使用rpm的方式安装mysql。
下载rpm包
wget http://dev.mysql.com/get/mysql57-community-release-el7-8.noarch.rpm
如果出现-bash: weget: command not found,需要yum install -y wget
如果安装不了,就使用wget配置镜像仓库(阿里云、网易云等),具体操作步骤如下:
1)备份CentOS-Base.repo:mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup;
2)下载阿里云镜像:wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo;
3)清理缓存:yum clean all;
4)生成缓存:yum makeache;
5)更新最新源设置:yum update -y;
yum localinstall mysql57-community-release-el7-8.noarch.rpm
yum repolist enabled
yum -y install mysql-community-server --nogpgcheck
与mysql启停相关的命令如下
systemctl start mysqld
systemctl stop mysqld
systemctl restart mysqld
执行启动命令之后,查看启动状态
systemctl status mysqld
yum安装mysql默认文件路径(在my.cnf不做其他配置的情况下)
默认配置文件路径: 配置文件:/etc/my.cnf
日志文件:/var/log/mysqld.log
服务启动脚本:/usr/lib/systemd/system/mysqld.service
socket文件:/var/run/mysqld/mysqld.pid
插件目录:/usr/lib64/mysql/plugin;
mysql安装完后,在文件中给生成一个默认密码,如果后续需要在其他客户端登录,需要重新修改密码并授权,通过下面的方式找到这个密码:
grep 'temporary password' /var/log/mysqld.log
找到这个密码之后,使用命令登录进去,但是从mysql5.7之后的某个版本开始,登录之后使用下面的命令直接修改的话,可能会报下面的错误;
set password=password('123456');
这个意思是说,mysql5.7默认安装了密码安全检查插件,默认密码检查策略要求密码必须包含:大小写字母、数字和特殊符号,并且长度不能少于8位。通过下面的命令可以查看密码策略的相关信息
show variables like '%password%';
关于参数具体含义,可以查阅相关的资料,网上比较丰富,为了简化后续的操作,这里提供一种比较简单的修改方式;
密码修改策略
在/etc/my.cnf文件添加validate_password_policy配置,指定密码策略,配置如下:
validate_password_policy=0
# 选择0(LOW),1(MEDIUM),2(STRONG)其中一种,选择2需要提供密码字典文件
如果不需要密码策略,添加my.cnf文件中添加如下配置禁用即可:
validate_password=off
上面的配置完成之后,最后重启mysql服务,再次登录到mysql客户端,重新修改mysql的root密码
set password=password('123456');
grant all on *.* to root@'%' identified by '123456';
flush privileges;
mysql主从的配置中,主节点必不可少的配置,一个是开启二进制日志,另一个是主从节点的server-id不能一样,首先在主节点添加下面的配置信息
log-bin=mysql-bin
binlog-format=ROW
server_id=1
修改完成后,重启主节点服务,然后在mysql安装目录下就可以看到bin-log的文件了
整个搭建的过程基本相同,执行步骤一直到启动mysql从节点的服务即可,这里就不再赘述了,参考上面的步骤执行即可;
分别在master节点和slave节点的my.cnf中做如下配置
参照上面步骤如果配置过了可忽略
在/etc目录下找到my.cnf,添加下面的配置,确保主从节点的server-id不同
server-id=2
在master节点上面执行创建slave用于同步数据的账号
create user master@'从数据库IP' identified with mysql_native_password by 'master_pass';
grant replication slave on *.* to master@'从数据库IP' identified by 'master_pass';
flush privileges;
查看master状态
show master status;
从服务器登录进客户端之后依次执行下面的命令
#停止本机的同步
stop slave;
#配置从服务器连接主服务器的配置项
change master to master_host='master 的IP',master_user='master',master_password='123456',master_log_file='mysql-bin.000001',master_log_pos=864;
#刷新
flush privileges;
查看同步状态
show slave status\G;
#开启slave状态
start slave;
show slave status\G;
当看到下面的这两个位置都为 Yes的时候说明主从环境配置完成;
在master上面创建一个数据库,创建一张表,并写入几条数据,检查是否能在从节点完成同步
create database test;
use test;
CREATE TABLE `tb_user` (
`id` int(12) NOT NULL,
`name` varchar(32) DEFAULT NULL,
`age` int(12) DEFAULT NULL,
`subject` varchar(32) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
insert into tb_user values (1,'liubei',33,'java');
到这里主从复制的环境就基本上搭建完成,接下来我们将基于该环境搭建出半同步复制的环境。
深入了解过主从模式的同学应该知道,在主从模式下,数据写入master时,并不关注后续数据是否成功写入到slave,即这是一个异步的过程,这样的一个比较明显的问题就是,假如数据同步过程中发生什么问题,master是无感知的,这样就造成了数据的不一致,此时假如请求发到slave上,可能造成读取数据失败的问题。有没有什么机制可以保证同步数据的准确性呢?可以考虑使用半同步复制的模式。
所谓的半同步复制就是master每commit一个事务(简单来说就是做一个改变数据的操作),要确保slave接受完主服务器发送的binlog日志文件并写入到自己的中继日志relay log里,然后会给master信号,告诉对方已经接收完毕,这样master才能把事物成功commit。
这样就保证了master-slave的数据绝对一致(但是以牺牲master的性能为代价),不过由于slave的同步写入数据需要一定时间,所以整个过程的时间会拉长,但等待slave响应的时间也是可以调整的。可以结合下面这张半同步复制的流程图进行理解。
完成mysql主从架构的搭建(上面已经完成);
半同步复制模式的实现需要借助mysql插件,其实在安装完成mysql之后,就默认带了一些插件工具,基于上述rpm的方式安装,插件的目录位置:/usr/lib64/mysql/plugin
master节点安装如下插件,进入客户端命令行,执行下面的语句;
install plugin rpl_semi_sync_master soname 'semisync_master.so';
检查是否安装成功,安装成功后,就能看到该插件相关的选项信息;
show global variables like 'rpl_semi_sync%';
slave节点安装如下插件,进入客户端命令行,执行下面的语句;
install plugin rpl_semi_sync_slave soname 'semisync_slave.so';
show global variables like 'rpl_semi_sync%';
上面在master和slave节点分别安装了半同步复制的插件,此时状态均为OFF,接下来需要对插件进行激活;
master节点执行如下命令激活,在上一步的基础上执行,激活后再次确认状态;
set global rpl_semi_sync_master_enabled=on;
show global variables like 'rpl_semi_sync%';
slave节点执行如下命令激活,在上一步的基础上执行,激活后再次确认状态;
set global rpl_semi_sync_slave_enabled=on;
show global variables like 'rpl_semi_sync%';
在上面的基础上,即slave客户端窗口执行下面的语句重启IO线程
stop slave IO_THREAD;
start slave IO_THREAD;
从上文关于半同步复制原理了解到,当slave从库的IO_Thread 线程将binlog日志接受完毕后,要给master一个确认,如果超过10s未收到slave的接收确认信号,那么就会自动转换为传统的异步复制模式。接下来看具体的操作步骤。
基于上面环境,master中test库下给tb_user表插入一条数据
insert into tb_user values (2,'zhaoyun',23,'flink');
如果插入成功,使用下面的语句,查看slave是否有成功返回
show global status like 'rpl_semi_sync%_yes_tx';
Value为1:表示这次事物成功从slave返回一次确认信号 ,以后每成功一次,数字会依次递增
同时检查slave这边,可以看到数据同步写入成功
假如环境中此时slave发生故障会怎么样呢?停止slave的mysql
systemctl stop mysqld
再次向master插入一条新数据
insert into tb_user values (3,'guanyu',35,'go');
从效果不难发现,sql语句执行等待了10秒钟,这就是在半同步复制模式下,master等待slave响应默认的等待时间,此时再次在master插入一条数据;
insert into tb_user values (5,'zhangliao',28,'hadoop');
这一次很快就执行完成了,因为基于 这种模式下,在上一步master这边发现slave挂掉了,于是就自动转成了原来的异步模式。
重新启动slave的mysql服务,并开启半同步复制,依次执行下面的语句
systemctl restart mysqld
set global rpl_semi_sync_slave_enabled=on;
stop slave IO_THREAD;
start slave IO_THREAD;
当上面的步骤完成后,主从半同步复制又开启了,同时,slave服务停掉期间在master上面插入的两条数据也再次同步过来了;
master需要等到slave确认后才能提交,如果等不到确认消息,master等待10s种后自动变成异步同步;slave启起来后,master上改变的数据还是会自动复制过来,数据又回到一致。
此时再次在master节点上再次插入一条数据,slave中能够查到,说明数据同步功能也恢复正常;
insert into tb_user values (6,'zhangfei',38,'python');
在上面的故障模拟中,第一次master默认的等待时间为10s,如果觉得太长,可以通过执行下面的语句调整
set global rpl_semi_sync_master_timeout=5000;
show global variables like 'rpl_semi_sync%';
如果不想再使用该插件了,可以通过下面的命令进行卸载
#查看系统中的插件
select plugin_name,load_option from information_schema.plugins;
#卸载某个插件
uninstall plugin 插件名称;
在某些情况下,当使用上面的命令先停止slave的mysql服务,然后再重新启动,登录到客户端之后,使用 show slave status命令的时候,发现下面两个参数的状态均为NO;
Slave_IO_Running NO
Slave_SQL_Running: NO
这种情况表明,mysqld重启后,主从同步也会随之关闭,需要手动重新开启,执行下面的命令即可重新建立slave与master的关系;
start slave;
本文通过较大的篇幅详细阐述了mysql主从复制的相关技术,以及基于mysql主从复制基础上如何搭建和配置mysql半同步复制模式,在生产实践中具有一定的参考性,希望对看到的你有用哦,本篇到此结束,感谢观看。