主从复制:主从复制的概述一主一从架构搭建主从复制的原理同步数据一致性问题

Posted 冬竹️

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了主从复制:主从复制的概述一主一从架构搭建主从复制的原理同步数据一致性问题相关的知识,希望对你有一定的参考价值。

文章目录

1. 主从复制的概述

1.1 如何提升数据库的并发能力

在实际工作中,我们常常将Redis作为缓存与mysql配合来使用,当有请求的时候,首先会从缓存中进行查找,如果存在就直接取出。如果不存在再访问数据库,这样就提升了读取的效率,也减少了对后端数据库的访问压力。Redis的缓存架构是高并发架构中非常重要的一环。

此外,一般应用对数据库而言都是“读多写少”,也就说对数据库读取数据的压力比较大,有一个思路就是采用数据库集群的方案,做主从架构、进行读写分离,这样同样可以提升数据库的并发处理能力。但并不是所有的应用都需要对数据库进行主从架构的设置,毕竟设置架构本身是有成本的。

如果我们的目的在于提升数据库高并发访问的效率,那么首先考虑的是如何优化SQL和索引,这种方式简单有效;其次才是采用缓存的策略,比如使用Redis将热点数据保存在内存数据库中,提升读取的效率;最后才是对数据库采用主从架构,进行读写分离。

按照上面的方式进行优化,使用和维护的成本是由低到高的。

1.2 主从复制的作用

主从同步设计不仅可以提高数据库的吞吐量,还有以下3个方面的作用。

第1个作用:读写分离。我们可以通过主从复制的方式来同步数据,然后通过读写分离提高数据库并发处理能力。

其中一个是Master主库,负责写入数据,我们称之为:写库。

其它都是Slave从库,负责读取数据,我们称之为:读库。

当主库进行更新的时候,会自动将数据复制到从库中,而我们在客户端读取数据的时候,会从从库中进行读取。

面对“读多写少”的需求,采用读写分离的方式,可以实现更高的并发访问。同时,我们还能对从服务器进行负载均衡,让不同的读请求按照策略均匀地分发到不同的从服务器上,让读取更加顺畅。读取顺畅的另一个原因,就是减少了锁表的影响,比如我们让主库负责写,当主库出现写锁的时候,不会影响到从库进行SELECT的读取。

第2个作用就是数据备份。我们通过主从复制将主库上的数据复制到了从库上,相当于是一种热备份机制,也就是在主库正常运行的情况下进行的备份,不会影响到服务。

第3个作用是具有高可用性。数据备份实际上是一种冗余的机制,通过这种冗余的方式可以换取数据库的高可用性,也就是当服务器出现故障宕机的情况下,可以切换到从服务器上,保证服务的正常运行。

关于高可用性的程度,我们可以用一个指标衡量,即正常可用时间/全年时间。比如要达到全年99.999%的时间都可用,就意味着系统在一年中的不可用时间不得超过365*24*60*(1-99.999%)=5.256分钟(含系统崩溃的时间、日常维护操作导致的停机时间等),其他时间都需要保持可用的状态。

实际上,更高的高可用性,意味着需要付出更高的成本代价。在现实中我们需要结合业务需求和成本来进行选择。

2. 主从复制的原理

Slave会从Master读取binlog来进行数据同步。

2.1 原理剖析

二进制日志转储线程(Binlog dump thread)是一个主库线程。当从库线程连接的时候,主库可以将二进制日志发送给从库,当主库读取事件(Event)的时候,会在Binlog上加锁,读取完成之后,再将锁释放掉。

从库I/O线程会连接到主库,向主库发送请求更新Binlog。这时从库的I/O线程就可以读取到主库的二进制日志转储线程发送的Binlog更新部分,并且拷贝到本地的中继日志(Relay log)。

从库SQL线程会读取从库中的中继日志,并且执行日志中的事件,将从库中的数据与主库保持同步。

2.2 复制的最大问题

延时

2.3 复制的基本原则

  • 每个Slave只有一个Master
  • 每个Slave只能有一个唯一的服务器ID
  • 每个Master可以有多个Slave

3. 一主一从架构搭建

一台主机用于处理所有写请求,一台从机负责所有读请求,架构图如下:

3.1 准备工作

  1. 准备2台CentOS虚拟机
  2. 每台虚拟机上需要安装好MySQL(可以是MySQL8.0)

3.2 主机配置文件

建议mysql版本一致且后台以服务运行,主从所有配置项都配置在[mysqld]节点下,且都是小写字母。

  • 必选
#[必须]主服务器唯一ID
server-id=1
#[必须]启用二进制日志,指名路径。比如:自己本地的路径/log/mysqlbin
log-bin=/log/mysqlbin
  • 可选
#[可选]0(默认)表示读写(主机),1表示只读(从机)
read-only=8

#设置日志文件保留的时长,单位是秒
binlog_expire_logs_seconds=6090

#控制单个二进制日志大小,此参数的最大和默认值是1GB
max_binlog_size=200M

#[可选]设置不要复制的数据库
binlog-ignore-db=test

#[可选]设置雨要复制的数据库,默认全部记录。比如:binlog-do-db=atguigu_master_slave
binlog-do-db=需要复制的主数据库名字

#[可选]设置binlog格式
binlog_format=STATEMENT

重启后台mysql服务,使配置生效。

3.3 从机配置文件

要求主从所有配置项都配置在my.cnf[mysqld]栏位下,且都是小写字母。

  • 必选
#[必选]从服务器唯一ID
server-id=2
  • 可选
#[可选]启用中继日志
relay-log=mysql-relay

重启后台mysql服务,使配置生效。

3.4 建立账户并授权

#在主机MySQL里执行授权主从复制的命令
GRANT REPLICATION SLAVE ON *.* TO 'slave1'@'从机器数据库IP'IDENTIFIED BY'abc123';#5.5,5.7

注意:如果使用的是MySQL8,需要如下的方式建立账户,并授权slave:

CREATE USER 'slave1'@ '%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE ON *.* TO 'slave1'@ '%';
#此语句必须执行。否则出错。
ALTER USER 'slave1'@ '%' IDENTIFIED WITH mysql_native_password BY '123456';
flush privileges;

查询Master的状态,并记录下File和Position的值。

show master status;

3.5 配置需要复制的主机

**步骤1:**从机上复制主机的命令

CHANGE MASTER TO
MASTER_HOST='主机的IP地址',
MASTER_USER='主机用户名',
MASTER_PASSWORD='主机用户名的密码',
MASTER_LOG_FILE='mysql-bin.具体数字',
MASTER_LOG_POS=具体值;

步骤2:

#启动slave同步
START SLAVE;

3.6 测试

主机新建库、新建表、insert记录,从机复制:

3.7 停止主从同步

stop slave;

4. 同步数据一致性问题

主从同步的要求

  • 读库和写库的数据一致(最终一致);
  • 写数据必须写到写库;
  • 读数据必须到读库(不一定);

4.1 理解主从延迟问题

进行主从同步的内容是二进制日志,它是一个文件,在进行网络传输的过程中就一定会存在主从延迟(比如500ms),这样就可能造成用户在从库上读取的数据不是最新的数据,也就是主从同步中的数据不一致性问题。

4.2 解决一致性问题

  • 异步复制
    异步模式就是客户端提交COMMIT之后不需要等从库返回任何结果,而是直接将结果返回给客户端,这样做的好处是不会影响主库写的效率,但可能会存在主库宕机,而Binlog还没有同步到从库的情况,也就是此时的主库和从库数据不一致。这时候从从库中选择一个作为新主,那么新主则可能缺少原来主服务器中已提交的事务。所以,这种复制模式下的数据一致性是最弱的。
  • 半同步复制

MySQL5.5版本之后开始支持半同步复制的方式。原理是在客户端提交COMMIT之后不直接将结果返回给客户端,而是等待至少有一个从库接收到了Binlog,并且写入到中继日志中,再返回给客户端。

这样做的好处就是提高了数据的一致性,当然相比于异步复制来说,至少多增加了一个网络连接的延迟,降低了主库写的效率。

在MysQL5.7版本中还增加了一个rpl_semi_sync_master_wait_for_slave_count参数,可以对应答的从库数量进行设置,默认为1,也就是说只要有1个从库进行了响应,就可以返回给客户端。如果将这个参数调大,可以提升数据一致性的强度,但也会增加主库等待从库响应的时间。

  • 组复制

异步复制和半同步复制都无法最终保证数据的一致性问题,半同步复制是通过判断从库响应的个数来决定是否返回给客户端,虽然数据一致性相比于异步复制有提升,但仍然无法满足对数据一致性要求高的场景,比如金融领域。MGR很好地弥补了这两种复制模式的不足。

组复制技术,简称MGR(MySQL Group Replication)。是MySQL在5.7.17版本中推出的一种新的数据复制技术,这种复制技术是基于Paxos协议的状态机复制。

MGR是如何工作的

首先我们将多个节点共同组成一个复制组,在执行读写(RW)事务的时候,需要通过一致性协议层(Consensus层)的同意,也就是读写事务想要进行提交,必须要经过组里“大多数人”(对应Node节点)的同意,大多数指的是同意的节点数量需要大于(N/2+1),这样才可以进行提交,而不是原发起方一个说了算。而针对只读(RO)事务则不需要经过组内同意,直接COMMIT即可。

在一个复制组内有多个节点组成,它们各自维护了自己的数据副本,并且在一致性协议层实现了原子消息和全局有序消息,从而保证组内数据的一致性。

mysql主从复制原理及一主一从搭建过程—2023.04

文章目录

一、MySQL主从复制介绍

1、主从复制概念

MySQL 主从复制是指数据可以从一个MySQL数据库服务器主节点复制到一个或多个从节点。

MySQL主从复制是一个异步的复制过程,底层是基于Mysql数据库自带的 二进制日志 功能。就是一台或多台MySQL数据库(slave,即从库)从另一台MySQL数据库(master,即主库)进行日志的复制,然后再解析日志并应用到自身,最终实现从库的数据和主库的数据保持一致。

2、为什么要做主从复制

  1. 在业务复杂的系统中,有这么一个情景,有一句sql语句需要锁表,导致暂时不能使用读的服务,那么就很影响运行中的业务,使用主从复制,让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。

  2. 做数据的热备

  3. 架构的扩展。业务量越来越大,I/O访问频率过高,单机无法满足,此时做多库的存储,降低磁盘I/O访问的频率,提高单个机器的I/O性能。

3、主从复制原理

  • 原理
  1. master服务器将数据的改变记录二进制binlog日志,当master上的数据发生改变时,则将其改变写入二进制日志中;
  2. slave服务器会在一定时间间隔内对master二进制日志进行探测其是否发生改变,如果发生改变,则开始一个I/OThread请求master二进制事件;
  3. 同时主节点为每个I/O线程启动一个dump线程,用于向其发送二进制事件,并保存至从节点本地的中继日志(relay-log)中,从节点将启动SQL线程从中继日志中读取二进制日志,在本地重放,使得其数据和主节点的保持一致,最后I/OThread和SQLThread将进入睡眠状态,等待下一次被唤醒。

也就是说:

  1. 从库会生成两个线程,一个I/O线程,一个SQL线程;
  2. I/O线程会去请求主库的binlog,并将得到的binlog写到本地的relay-log(中继日志)文件中;
  3. 主库会生成一个log dump线程,用来给从库I/O线程传binlog;
  4. SQL线程,会读取relay log文件中的日志,并解析成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
  • 主从同步事件binlog模式有3种形式:statementrowmixed
  1. statement: 会将对数据库操作的 sql 语句写入到 binlog 中。
  2. row: 会将每一条数据的变化写入到 binlog 中。
  3. mixed: statement 与 row 的混合。MySQL 决定什么时候写 statement 格式的,什么时候写 row 格式的 binlog。
  • 注意:
    ①master将操作语句记录到binlog日志中,然后授予slave远程连接的权限(master一定要开启binlog二进制日志功能;通常为了数据安全考虑,slave也开启binlog功能)。
    ②slave开启两个线程:IO线程和SQL线程。其中:IO线程负责读取master的binlog内容到中继日志relay log里;SQL线程负责从relay log日志里读出binlog内容,并更新到slave的数据库里,这样就能保证slave数据和master数据保持一致了。
    ③Mysql复制至少需要两个Mysql的服务,当然Mysql服务可以分布在不同的服务器上,也可以在一台服务器上启动多个服务。
    ④Mysql复制最好确保master和slave服务器上的Mysql版本相同(如果不能满足版本一致,那么要保证master主节点的版本低于slave从节点的版本)
    ⑤master和slave两节点间时间需同步

4、主从复制形式

  1. 一主多从,提高系统的读性能

    一主一从和一主多从是最常见的主从架构,实施起来简单并且有效,不仅可以实现HA,而且还能读写分离,进而提升集群的并发能力。
  2. 多主一从 (从5.7开始支持)

    多主一从可以将多个mysql数据库备份到一台存储性能比较好的服务器上。
  3. 双主复制
    双主复制,也就是互做主从复制,每个master(主)既是master,又是另外一台服务器的slave(从)。这样任何一方所做的变更,都会通过复制应用到另外一方的数据库中。
  4. 级联复制

    级联复制模式下,部分slave的数据同步不连接主节点,而是连接从节点。因为如果主节点有太多的从节点,就会损耗一部分性能用于replication(复制),那么我们可以让3~5个从节点连接主节点,其它从节点作为二级或者三级与从节点连接,这样不仅可以缓解主节点的压力,并且对数据一致性没有负面影响。级联复制下从节点也要开启binary log(bin-log)功能。

5、主从复制主要用途

  1. 读写分离
    在开发工作中,有时候会遇见某个sql 语句需要锁表,导致暂时不能使用读的服务,这样就会影响现有业务,使用主从复制,让主库负责写,从库负责读,这样,即使主库出现了锁表的情景,通过读从库也可以保证业务的正常运作。
  2. 数据实时备份,当系统中某个节点发生故障时,可以方便的故障切换(主从切换)
    提高数据安全-因为数据已复制到从服务器,从服务器可以终止复制进程,所以,可以在从服务器上备份而不破坏主服务器相应数据;
  3. 高可用(HA)
    1)因为数据库服务器中的数据都是相同的,当Master挂掉后,可以指定一台Slave充当Master继续保证服务的运行,因为数据是一致性的(如果当插入时Master就挂掉,可能不一致,因为同步也需要时间)当然这种配置不是简单的把一台Slave充当Master,毕竟还要考虑后续的Slave的数据同步到Master
    2)在主服务器上执行写入和更新,在从服务器上向外提供读功能,达到读写分离的效果,也可以动态地调整从服务器的数量,从而调整整个数据库的性能。
    3)在主服务器上生成实时数据,而在从服务器上分析这些数据,从而提高主服务器的性能。
  4. 架构扩展
    随着系统中业务访问量的增大,如果是单机部署数据库,就会导致I/O访问频率过高。有了主从复制,增加多个数据存储节点,将负载分布在多个从节点上,降低单机磁盘I/O访问的频率,提高单个机器的I/O性能。

二、MySQL一主一从搭建

1、准备工作

服务器 IP 要求
master 192.168.2.31 Docker、MySQL5.7
slave 192.168.2.32 Docker、MySQL5.7

首先在两台服务器上提前部署好docker以及MySQL5.7版本。

MySQL安装流程参考这篇文章:https://blog.csdn.net/weixin_64124795/article/details/129110551

2、MySQL主从复制部署流程

1. 关闭防火墙,两台主机都操作

systemctl stop firewalld  关闭防火墙
systemctl disable firewalld 关闭开机自启

2. 修改配置文件,两台主机都操作

mysql配置文件路径:/etc/my.cnf
增加如下内容:

# MySQL 服务的唯一编号,每个 MySQL 服务的 id 需唯一
server-id = 1

# 服务端口号,默认为 3306
port = 3306

# 是否对sql语句大小写敏感,默认值为0,1表示不敏感
lower_case_table_names=1    #1代表关闭大小写区别 0代表开启大小写

default_storage_engine=InnoDB   #存储引擎  lnnoDB

# 配置默认编码为utf8
character_set_server=utf8
init_connect=\'SET NAMES utf8\'

最终配置文件内容:

# For advice on how to change settings please see
# http://dev.mysql.com/doc/refman/5.7/en/server-configuration-defaults.html

[mysqld]

# MySQL 服务的唯一编号,每个 MySQL 服务的 id 需唯一
server-id = 1

# 服务端口号,默认为 3306
port = 3306

# 是否对sql语句大小写敏感,默认值为0,1表示不敏感
lower_case_table_names=1    #1代表关闭大小写区别 0代表开启大小写

default_storage_engine=InnoDB   #存储引擎  lnnoDB

# 配置默认编码为utf8
character_set_server=utf8
init_connect=\'SET NAMES utf8\'
#
# Remove leading # and set to the amount of RAM for the most important data
# cache in MySQL. Start at 70% of total RAM for dedicated server, else 10%.
# innodb_buffer_pool_size = 128M
#
# Remove leading # to turn on a very important data integrity option: logging
# changes to the binary log between backups.
# log_bin
#
# Remove leading # to set options mainly useful for reporting servers.
# The server defaults are faster for transactions and fast SELECTs.
# Adjust sizes as needed, experiment to find the optimal values.
# join_buffer_size = 128M
# sort_buffer_size = 2M
# read_rnd_buffer_size = 2M
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock

# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0

log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

重启mysql使配置生效

systemctl restart mysqld

默认配置文件路径:
配置文件:/etc/my.cnf
日志文件:/var/log/mysqld.log
服务启动脚本:/usr/lib/systemd/system/mysqld.service
socket文件:/var/lib/mysql/mysql.sock

3. 修改主节点配置文件,主节点操作

vim /etc/my.cnf添加以下参数:

log-bin=mysql-bin #启动二进制日志系统

binlog-do-db=test #二进制需要同步的数据库名,如果需要同步多个库,例如要再同步westos库,再添加一行“binlog-do-db=westos”,以此类推

binlog-ignore-db=mysql #禁止同步 mysql 数据库

# 重启mysql
systemctl restart mysqld
  • 配置主服务器用户并清空日志
    进入MySQL
mysql -uroot -p
mysql> show privileges;
# 注意这里的密码不能设置的太简单,否则会报错 ERROR 1819 (HY000): Unknown error 1819
mysql> grant replication client,replication slave on *.* to \'tongwz\'@\'192.168.2.%\' identified by \'Tongwz123.\';
mysql> reset master;
mysql> show binary logs;

4. 修改从节点配置文件,从节点操作

/etc/my.cnf中的server-id 改为2, 注意:server-id不可跟主服务器的一样

# 重启mysql
systemctl restart mysqld

进入MySQL:

mysql -uroot -p

执行如下命令:

mysql> change master to master_host=\'192.168.2.31\', master_user=\'tongwz\', master_password=\'Tongwz123.\', master_port=3306, master_log_file=\'mysql-bin.000001\', master_log_pos=154;


说明:
# change master to master_host=‘主服务器ip’,
# master_user=‘刚在主服务器创建的用户名’,
# master_password=‘刚在主服务器创建的用户密码’, 
# master_port=3306, 
# master_log_file=‘刚查看主服务器下的File值’,
# master_log_pos=刚查看主服务器下的Position值,必须要一致
先查看slave状态:红框中显示是No,由于slave还没有开启,表示还没有加入主节点
mysql> show slave status \\G;

正式开启slave:
mysql> start slave;
再次查看状态:此时已经显示为Yes了
mysql> show slave status \\G;


注意:两个必须都显示为Yes才表示成功,否则就要重新执行change master to master_host=\'192.168.2.31\', master_user=\'tongwz\', master_password=\'Tongwz123.\', master_port=3306, master_log_file=\'mysql-bin.000001\', master_log_pos=154;这段命令,在执行这段命令前还需要通过show binary logs;命令查看master节点aster_log_pos值。

此时,slave已经配置好,进一步查看:

# 查看relay-log.info文件位置,进入查看
find / -name relay-log.info
cat /var/lib/mysql/relay-log.inf

# 查看master.info文件位置,进入查看
find / -name master.info
cat /var/lib/mysql/master.info


5. 测试

在master节点中数据库test里创建表test,插入数据;在slave节点查看数据是否同步。
因为前面配置文件中,写明了只同步test数据库。

master节点中创建:
mysql> use test;
mysql> create table test(id int(11));
mysql> insert into test values(1);
mysql> select * from test;
slave节点中查看:
mysql> use test;
mysql> show tables;
mysql> select * from test;


可以看到在master节点上加入的数据,这就

6. 特别说明

  1. 以上这种方式搭建的一主一从,主要实现读写分离,master节点上写入数据会自动同步到slave节点。如果反过来,在slave节点写入数据,是无法同步到master节点上的,反而还会中断主节点与从节点的连接。所以为了避免这个问题,一般只给slave节点只读的权限。
增加同步的数据库到slave
  1. 上面的操作我们只同步了test数据库,如果我们想要再同步一个数据库到slave节点,该怎么操作呢?
    首先,我们要修改master节点的配置文件vim /etc/my.cnf,里面增加数据库test1
    master节点操作:
vim /etc/my.cnf


binlog-do-db=test  #二进制需要同步的数据库名,如果需要同步多个库,例如要再同步westos库,再添加一行“binlog-do-db=westos”,以此类推
binlog-do-db=test1   # 增加这一行

然后重启

systemctl restart mysqld

然后,进入slave节点的mysql中,等待从节点同步主节点数据,待查看状态show slave status \\G;后,两行都显示为Yes,表示已经连接成功;

其次,再master节点上的mysql中创建test1数据库,并往数据库内创建表,写入内容;

最后到slave节点查看是否同步即可。

注意:
必须先修改配置文件中的数据库名称,然后待slave与master连接后,再在master上创建test1数据库,顺序不能改变。
如果反过来,先在master节点上创建了test1数据库,然后修改配置文件、slave连接master,那么所创建的数据库就不会同步到slave。
所以,顺序很重要。
slave只同步连接master节点后,在master节点上执行的命令。

以上是关于主从复制:主从复制的概述一主一从架构搭建主从复制的原理同步数据一致性问题的主要内容,如果未能解决你的问题,请参考以下文章

MySQL主从复制的简单搭建

MySQL主从复制的简单搭建

MySQL主从复制的简单搭建

mysql搭建主从复制(一主一从,双主双从)

mysql之 mysql 5.6不停机主从搭建(一主一从基于GTID复制)

使用多实例进行主从复制实践案例(一主一从)