【LInux】MySQL高可用之主从复制

  • Post author:
  • Post category:linux


一、Mysql主从架构技术说明


Mysql内建的复制功能是构建大型,高性能应用程序的基础

。将Mysql的数据分布到 多个系统上去,这种分布的机制,是通过将Mysql的某一台主机(Master)的数据复 制到其它主(slaves)上,并重新执行一遍来实现的。 复制过程中一个服务器充当主服务器,而一个或多个其它服务器充当从服务器。主服 务器将更新写入二进制日志文件,这些日志可以记录发送到从服务器的更新。当一个 从服务器连接主服务器时,它通知主服务器从服务器在日志中读取的最后一次成功更 新的位置。从服务器接收从那时起发生的任何更新,然后封锁并等待主服务器通知新的更新。

1. 主从复制架构图

二进制日志也就是binlog.log,它里面记录的数据库的操作;


主机数据库的操作记录在二进制日志里;


从机有两个线程:

  • I/O线程

    • 用来读取主机上的二进制日志的内容,写入到中继日志(relay_log)
  • SQL线程

    • 将中继日志中的数据读取给从机(因为二进制日志里的内容是sql语句,所以中继日志里的内容也是sql语句,这时候就需要sql线程将中继日志的内容读取,读取后相当于在从机上执行了sql语句,这样实现了主从复制)

2、Mysql复制解决的问题

MySQL复制技术有以下一些特点:

  1. 数据分布 (Data distribution )
  2. 负载平衡(load balancing)
  3. 备份(Backups)
  4. 高可用性和容错性 High availabilityand failover


主从复制以及主从复制的作用: 在实际的生产环境中,对数据库的读和写都在同一个数据库服务器中,是不能满足 实际需求的,通过主从复制的方式来同步数据,再通过读写分离来提升数据库的并发 负载能力


3、

MySQL主从复制的复制方式

1)异步复制(Asynchronous replication)


MySQL的复制默认是异步的,MySQL主从异步复制是最常见的复制场景

。数据的完

整性依赖于主库BINLOG的不丢失,只要主库的BINLOG不丢失,那么就算主库宕机

了,我们还可以通过BINLOG把丢失的部分数据通过手工同步到从库上去。



异步复制是指 主库在执行完客户端提交的事务后会立即将结果返给给客户端,并不

关心从库是否已经接收并处理

,这样就会有一个问题,主如果crash掉了,此时主上

已经提交的事务可能并没有传到从上,如果此时,强行将从提升为主,可能导致新主

上的数据不完整。

MySQL 默认的复制策略,Master处理事务过程中,将其写入Binlog就会通知Dump thread线程处理,然后完成事务的提交,不会关心是否成功发送到任意一个slave中;




【问题】:一旦Master 崩溃,发送主从切换将会发送数据不一致性的风险。



(也就是主机崩溃了,因为是异步,主机已经不再接受数据了,而从机还在同步就可能导致数据不一致)


画外音:性能最好


2)

全同步复制(Fully synchronous replication)/组复制 (MySQL Group Replication(MGR))


指当主库执行完一个事务,所有的从库都执行了该事务才返回给客户端

。因为需要等 待所有从库执行完该事务才能返回,所以全同步复制的性能必然会收到严重的影响。 需要有超时时间。

MySQL在引擎层完成Prepare操作写Redo日志之后,会被MySQL的预设Hook拦截 进入MGR层

MGR层将事务信息打包通过Paxos协议发送到全部节点上,只要集群中过半节点回复 ACK,那么将告诉所有节点数据包同步成功,然后每个节点开始自己认证(certify) 通过就开始写Binlog,提交事务或者写relay log,数据同步,如果认证不通过则 rollback;


什么是Certify? 在不同服务器上并发执行的事务之间可能存在冲突。这种冲突是通过检查和比 较两个不同的并发事务的写入集来检测的,这个过程称为认证 在认证期间,冲突检测是在行级别执行的:如果在不同服务器上执行的两个并 发事务更新了同一行,则存在冲突。 冲突解决过程指出,首先排序的事务将在所有服务器上提交,而第二次排序的 事务将中止,因此将在原始服务器上回滚并被组中的其他服务器丢弃。




总结:MGR内部实现了分布式数据一致性协议,paxos通过其来保证数据一致性。




【问题】

1. 性能不高

2. TP999升高,吞吐量降低;增大20%~30%响应时间

3)半同步复制(Semisynchronous replication)


介于异步复制和全同步复制之间,主库在执行完客户端提交的事务后不是立刻返回给 客户端,而是等待至少一个从库接收到并写到relay log中才返回给客户端。

相对于 异步复制,半同步复制提高了数据的安全性,同时它也造成了一定程度的延迟,这个 延迟最少是一个TCP/IP往返的时间。

所以,半同步复制最好在低延时的网络中使用。


Master处理事务过程中,提交完事务后,必须等至少一个Slave将收到的binlog写入 relay log返回ack才能继续执行处理用户的事务。




【问题】



  1. 一旦Ack超时,将退化为异步复制模式,那么异步复制的问题也将发送

  2. 性能下降,增多至少一个RTT时间

  3. 数据不一致性问题,因为等待ACK的点是Commit之后,此时Master已经完成 数据变更,用户已经可以看到最新数据,当Binlog还未同步到Slave时,发生主 从切换,那么此时从库是没有这个最新数据的,用户又看到老数据。

二、Mysql实现企业级数据库主从复制架构实战

1、准备两台服务器

centos系统服务器2台、一台用户做Mysql主服务器,一台用于做Mysql从服务器, 都在同一个网段中,配置好yum源、防火墙关闭、各节点时钟服务同步、各节点之间 可以通过主机名互相通信;


•Master_IP:192.168.198.142

•Slave_IP:192.168.198.148


注意:MySQL版本号最好一致,为了方便学习测试,建议大家直接克隆之前课 程安装过的虚拟机然后修改下网卡配置文件,重新设置一个IP,


并关闭防火墙


2、关闭防火墙和selinux

1)临时关闭防火墙,下次启动虚拟机防火墙依旧是开启状态

systemctl stop firewalld

2)永久关闭防火墙,下次启动虚拟机防火墙是关闭状态

systemctl disable firewalld

3)清理防火墙规则

 iptables -F

4)关闭selinx

① 编辑/etc/sysconfig/selinux文件

 vim /etc/sysconfig/selinux

将高亮显示的地方改为disabled

② 改完之后重启虚拟机

reboot

③ 查看selinux状态:

getenforce

3、更改从机的uuid

mysql 5.6以后的复制引入了uuid的概念,各个复制结构中的server_uuid得保证不一 样,但是查看到直接copy data文件夹后server_uuid是相同的;

① 查看主从机的uuid

show variables like '%server_uuid%';

② 修改从机的uuid

vim /var/lib/mysql/auto.cnf

将原本的24改为25

修改外之后保存退出;

③ 重启mysql服务,重新加载配置

 systemctl restart mysqld

④ 查看从机的uuid是否修改成功;

修改成功;


4、修改master主机配置


① 修改配置文件

vim /etc/my.cnf
[mysqld]
server-id=142        #配置server-id,让主服务器有唯一ID号(让从服务器知道他的主服务器是谁),建议使用ip最后3位
log-bin=mysql-bin    #打开Mysql日志,日志格式为二进制
skip-name-resolve    #关闭名称解析,(非必须)

② 然后重启数据库服务

 systemctl restart network

5、创建复制帐号

在Master的数据库中建立一个备份帐户:每个slave使用标准的MySQL用户名和密码 连接master。进行复制操作的用户会授予REPLICATION SLAVE权限。(给从服务器 授权,让它能从主服务器拷贝二进制日志)

create user 'copy'@'%' identified with mysql_native_password by
'Nebula@123';
GRANT REPLICATION SLAVE ON *.* TO 'copy'@'%';
flush privileges;

6、查看主服务器状态

show master status\G;

记录上图结果中File和Position的值。


注意:执行完此步骤后不要再操作主服务器MySQL,防止主服务器状态发生状态值变化。

7、配置slave从服务器

①  修改配置文件

vim /etc/my.cnf
[mysqld]
server-id=148    #配置server-id,让从服务器有唯一ID号,建议使用ip最后3位
relay_log=mysql-relay    #打开Mysql日志,日志格式为二进制
read_only=1    #设置只读权限
log_bin=mysql-bin    #开启从服务器二进制日志
log_slave_updates=1    #使得更新的数据写进二进制日志中

② 然后重启数据库服务

 systemctl restart mysqld

8、启动从服务器复制线程

①在从机上连接主机

【直接复制可能会有莫名其妙的报错,最好手敲一遍】

CHANGE MASTER TO
master_host = '192.168.198.142', #主库的IP地址
master_user = 'copy', #在主库上创建的复制账号
master_password = 'Nebula@123', #在主库上创建的复制账号密码
master_log_file = 'mysql-bin.000004', #开始复制的二进制文件名(从主库查询结果中获取)
master_log_pos = 773; #开始复制的二进制文件位置(从主
库查询结果中获取)

② 执行start slave;# 启动复制线程。

③ 出现红框的内容,表示主从复制配置成功

④ 测试主从复制是否成功

Master中和Slave中执行SQL:

 show databases;

Master:

Slave:

在Master中创建数据库并创建数据表并插入一条数据:

create database copy_test2;
use copy_test2;
create table tab1(id int auto_increment,name varchar(10),primary
key(id));
insert into tab1(id,name) values (1,'why');

⑥ 查看主从机是否都有copy_test2数据库;


9、mysql 主从数据不一致,提示:Slave_SQL_Running: No 的解决方法

在slave服务器上通过如下命令:

show slave status\G;

效果如下图所示,表示slave不同步



解决方法(忽略错误,继续同步):

① 先停掉slave

stop slave;

② 跳过错误步数,后面步数可变

set global sql_slave_skip_counter=1;

③ 再启动slave

start slave;

④ 查看同步状态

show slave status\G;



版权声明:本文为weixin_65690979原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。