自学内容网 自学内容网

MySQL主从复制原理与实现

主从复制的作用

  1. 数据冗余与容灾: 通过将数据复制到一个或多个从服务器,可以创建数据的冗余副本。在主服务器发生故障的情况下,可以从服务器迅速接管服务,避免数据丢失和业务中断,实现高可用性。
  2. 读写分离: 主从复制允许将写操作(如INSERT、UPDATE、DELETE)集中在主服务器上,而将读操作(如SELECT)分散到一个或多个从服务器上。这种读写分离的设计可以显著减轻主服务器的负载,提高读操作的响应速度和系统整体的处理能力。
  3. 负载均衡: 从服务器可以分担读操作的负载,实现负载均衡。对于读密集型的应用,这可以极大地提升性能和响应时间。

实现原理

一、binlog

binlog 是 mysql Server 层生成的日志文件。binlog 文件是记录了所有数据库表结构变更核表数据修改的日志,不会记录查询类的操作。如SELECT、SHOW 等操作。

binlog 是追加写,写满一个文件,就创建一个新的文件继续写,不会覆盖以前的日志,保存的是全量的日志。

因此binlog 可以用于备份恢复、主从复制;

二、主从复制实现

mysql 的主从复制依赖于binlog,具体的过程主要有以下三个步骤:

  • 主服务器开启binlog日志功能,记录所有改变数据的语句。
  • 从服务器通过一个IO线程连接到主服务器,请求从最后一个成功复制的位置开始的binlog文件,主服务器响应从服务器的请求,发送binlog日志事件给从服务器。从服务器接收到这些日志后,将其存储在本地的“中继日志”(Relay Log)中。中继日志本质上是主服务器binlog日志的副本,保存在从服务器上。
  • 从服务器开启SQL线程读取中继日志中的事件,并在从服务器的数据库上重放这些事件,以达到主从数据库之间的数据一致。

这个过程一般是异步的,也就是主库上执行事务操作的线程不会等待复制 binlog 的线程同步完成。
在这里插入图片描述
MySQL 主从复制模型:

  • 同步复制:主库提交事务的线程等待所有从库复制成功后才能响应客户端。性能很差。
  • 异步复制:主库的线程不需要等待从库复制成功,性能很好,但是主库一旦宕机,数据就会丢失。
  • 半同步复制:主库只需要等待部分从库复制成功即可,不需要等待全部成功,是一种折中的方法,性能不会很差,在主库宕机后,也至少有一个从库上有最新的数据,不会发生数据丢失。

基于docker 的主从复制实现

使用docker 创建两个mysql容器,一个作为主库,一个作为从库,实现主从复制。

1. 基于 docker-compose 创建主从容器

编写 docker-compose.yaml 文件

version: '3.1'

services:
  mysql-master:# 第一个service
    image: mysql:8.0.26 # 使用的镜像
    container_name: mysql-master # 容器名
    environment:# 设置mysql的密码核数据库的环境变量
      MYSQL_ROOT_PASSWORD: xxx
      MYSQL_DATABASE: db_name
    volumes:# 挂载卷
      - ./master/data:/var/lib/mysql# mysql 的数据挂在到宿主机的master/data
      - ./master/init/init.sql:/docker-entrypoint-initdb.d/init.sql:ro # 挂在数据库表脚本
    ports:# 端口映射
      - "3306:3306"
    command:
      --default-authentication-plugin=mysql_native_password# 默认认证插件
      --log-bin=mysql-bin# 开启binlog日志功能,基础名为 mysql-bin
      --server-id=1 # 指定唯一的ID
# 配置从服务器
  mysql-slave:
    image: mysql:8.0.26
    container_name: mysql-slave
    depends_on:
      - mysql-master
    environment:
      MYSQL_ROOT_PASSWORD: xxx
      MYSQL_DATABASE: db_name
    volumes:
      - ./slave/data:/var/lib/mysql
      - ./master/init/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    ports:
      - "3307:3306"
    command:
      --default-authentication-plugin=mysql_native_password
      --server-id=2
      --log-bin=mysql-bin
      --relay-log=relay-bin# 指定中继日志(relay log)文件的基本名称
      --read-only=1
volumes:
   master-data:
   slave-data:

启动容器:

docker-compose up -d

2. 配置主从复制

首先在主服务器中获取binlog的文件名和开始位置:

  • 进入主容器
  • 进入主容器的mysql
  • 执行SHOW MASTER STATUS\G

在这里插入图片描述
记录输出中的 FilePosition

进入从容器的MySQL,输入以下命令配置从节点的复制:

CHANGE MASTER TO
  MASTER_HOST='mysql-master',
  MASTER_USER='replicator',
  MASTER_PASSWORD='replicatorpassword',
  MASTER_LOG_FILE='mysql-bin.000003',  -- 使用上面记录的 File 值
  MASTER_LOG_POS=838;                  -- 使用上面记录的 Position 值

START SLAVE;

查看从节点状态:

SHOW SLAVE STATUS\G;

确保 Slave_IO_RunningSlave_SQL_Running 均为 Yes

在这里插入图片描述

验证:

在主节点表中插入数据,然后去从节点表中去看有没有插入同样的数据,如果有,则主从复制配置成功。

如果没有,则在从节点执行SHOW SLAVE STATUS\G;关注Last_Error 字段报错的问题。

3. bug记录

本人在创建时由于没有给从节点加载一样的数据库表结构,导致在主节点插入数据的时候从节点同步失败。Last_Error 字段报没有找到表。

解决方法就是在从节点的mysql中加载构建表的sql脚本,之后重新配置从节点的复制配置:

STOP SLAVE;
RESET SLAVE ALL;

CHANGE MASTER TO
  MASTER_HOST='mysql-master',
  MASTER_USER='replicator',
  MASTER_PASSWORD='replicatorpassword',
  MASTER_LOG_FILE='mysql-bin.000003',  -- 使用主节点的File值
  MASTER_LOG_POS=838;                  -- 使用主节点的Position值
  START SLAVE;
  SHOW SLAVE STATUS\G;

下一篇在此基础上实现读写分离:
MySQL实现读写分离


原文地址:https://blog.csdn.net/qq_44957574/article/details/140591590

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!