Skip to content

6_主从复制(MySQL,Redis)

理解

MySQL主从复制(MySQL Replication)是一种数据库级别的数据同步技术,它允许将一个MySQL数据库服务器(主服务器/ Master)上的数据更改自动地、异步地复制到一个或多个其他MySQL数据库服务器(从服务器/ Slave)。主从复制基于分布式数据库架构,用于实现数据冗余、故障切换、负载均衡以及读写分离。

基本原理

  1. 主服务器记录更改
    • 主服务器启用二进制日志(Binary Log),记录所有的数据库更改操作,包括INSERT、UPDATE、DELETE和其他DDL语句。每个事务在提交后都会以事件形式记录在二进制日志中。
  2. 从服务器拉取和重放更改
    • 从服务器会连接到主服务器,请求并接收主服务器的二进制日志内容。
    • 接收到的日志事件存储在从服务器的中继日志(Relay Log)中。
    • 从服务器的SQL线程读取中继日志,并按顺序重新执行这些事件,即在本地执行同样的SQL操作,使得从数据库的内容与主数据库保持一致。
  3. 数据同步流程
    • 从服务器启动I/O线程,该线程连接到主服务器并请求主服务器的二进制日志内容。
    • I/O线程接收到日志内容后,在本地写入中继日志。
    • SQL线程读取中继日志并执行其中的SQL语句,使从数据库与主数据库同步。
  4. 复制模式
    • MySQL支持不同类型的复制模式,如基于语句的复制、基于行的复制和混合模式。
  5. 读写分离
    • 在配置了主从复制的环境中,通常会将读密集型操作分发给从服务器处理,而主服务器专门处理写入操作,这样可以减轻主服务器的压力,提高系统的整体性能和可扩展性。
  6. 故障恢复和高可用
    • 如果主服务器出现故障,可以将某个从服务器提升为主服务器,继续提供服务,从而实现高可用性和灾难恢复。

总之,MySQL主从复制是通过日志传输和回放机制确保数据在多个服务器间保持一致性的关键技术手段。通过正确配置和管理主从复制结构,可以有效提高数据安全性、可用性和整个数据库系统的响应能力

基本流程

开始 ---->
       |
    主服务器 --------------+
       |                    |
     事务执行             |
       |          二进制日志记录 (Binary Log)
       +------------------------>
       |                    |
    启动I/O线程            |
       |         请求主服务器日志事件
       +-------------->
       |                    |
     接收日志事件        |
       |         写入中继日志(Relay Log)
       +------------------------>
       |
    启动SQL线程           |
       |         读取中继日志并执行
       +-------------->
       |
     数据同步              |
       |          从服务器数据更新
       +------------------------>
       |
    结束 <----

配置

主数据库

  • 新建主服务器
bash
docker run -p 3307:3306 --name mysql-master -v /mydata/mysql-master/log:/var/log/mysql -v /mydata/mysql-master/data:/var/lib/mysql -v /mydata/mysql-master/conf:/etc/mysql -e MYSQL_ROOT_PASSWORD=root  -d mysql:5.7
  • 新建配置目录下my.cnf
bash
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=101 
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql  
## 开启二进制日志功能
log-bin=mall-mysql-bin  
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M  
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed  
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7  
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062
  • 修改完成之后重启master
bash
docker restart mysql-master
  • 进入容器
bash
docker exec -it mysql-master /bin/bash
mysql -uroot -proot
  • 主服务器容器实例内创建数据同步用户
bash
CREATE USER 'slave'@'%' IDENTIFIED BY '123456';
GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'slave'@'%';

从数据库

bash
docker run -p 3308:3306 --name mysql-slave \
-v /mydata/mysql-slave/log:/var/log/mysql \
-v /mydata/mysql-slave/data:/var/lib/mysql \
-v /mydata/mysql-slave/conf:/etc/mysql \
-e MYSQL_ROOT_PASSWORD=root  \
-d mysql:5.7

新建配置文件my.cnf

bash
[mysqld]
## 设置server_id,同一局域网中需要唯一
server_id=102
## 指定不需要同步的数据库名称
binlog-ignore-db=mysql  
## 开启二进制日志功能,以备Slave作为其它数据库实例的Master时使用
log-bin=mall-mysql-slave1-bin  
## 设置二进制日志使用内存大小(事务)
binlog_cache_size=1M  
## 设置使用的二进制日志格式(mixed,statement,row)
binlog_format=mixed  
## 二进制日志过期清理时间。默认值为0,表示不自动清理。
expire_logs_days=7  
## 跳过主从复制中遇到的所有错误或指定类型的错误,避免slave端复制中断。
## 如:1062错误是指一些主键重复,1032错误是因为主从数据库数据不一致
slave_skip_errors=1062  
## relay_log配置中继日志
relay_log=mall-mysql-relay-bin  
## log_slave_updates表示slave将复制事件写进自己的二进制日志
log_slave_updates=1  
## slave设置为只读(具有super权限的用户除外)
read_only=1

重启

bash
docker restart mysql-slave

在主数据库中查看主从同步状态

bash
show master status

进入mysql-slave容器

bash
docker exec -it mysql-slave bash
mysql -uroot -p

在从数据库中配置主从复制

bash
change master to master_host='宿主机ip', master_user='slave', master_password='123456', master_port=3307, master_log_file='mall-mysql-bin.000001', master_log_pos=617, master_connect_retry=30;

在从数据库中查看主从同步状态

show slave status \G;

在从数据库中开启主从同步

bash
start slave

查看从数据库状态

bash
Slave_IO_Running:YES
Slave_SQL_Running:Yes

Redis主从复制原理与流程详解

Redis作为一个高性能的内存数据存储系统,被广泛应用于缓存、队列和实时计算等场景。为了保证服务的高可用性和扩展性,Redis提供了主从复制(Master-Slave Replication)机制。

  1. 建立连接
    • 从节点主动发起对主节点的连接,并请求成为其从节点。
    • 主节点接受连接请求。
  2. 全量复制(Initial Sync)
    • 第一次复制或长时间断开重连时进行全量复制:
      • 从节点发送 PSYNC 命令给主节点(在较新版本中,PSYNC 替代了旧版的 SYNC 命令),用于启动复制过程并尝试增量复制。
      • 如果是初次复制或者主从不一致导致无法增量复制,主节点执行 BGSAVE 命令创建一个RDB快照文件(Redis数据库的持久化格式)。
      • 主节点将生成的RDB文件发送给从节点,从节点加载这个文件以恢复主节点当前的数据状态。
      • 主节点将保存在缓冲区中的所有写命令发送给从节点,确保主从数据完全一致。
  3. 增量复制(Partial Sync)
    • 在完成全量复制后,主节点会继续将后续接收到的所有写命令记录到复制积压缓冲区,并同时维护一个复制偏移量。
    • 从节点也会记住自己的复制偏移量,并持续监听主节点的输出日志(replication stream)。
    • 当网络中断后重新连接时,从节点再次发送 PSYNC 命令,带上自己最后处理过的复制偏移量以及主节点运行ID。
    • 如果主从节点的复制上下文匹配,主节点将只传输从节点丢失的部分命令(部分复制),否则仍会触发全量复制。
  4. 心跳检测与命令传播
    • 主从节点之间会定期通过心跳检测维持连接状态。
    • 主节点每执行完一个写命令都会向所有从节点广播该命令。
    • 从节点接收并执行这些相同的写命令,从而保证主从数据的一致性。

流程图简述

  • 开始:从节点连接主节点

  • 判断是否首次复制:

    • 是:主节点执行BGSAVE -> 发送RDB文件至从节点 -> 发送缓冲区中的写命令
    • 否:从节点发送上次复制的偏移量和主节点ID -> 根据情况决定全量或增量复制
  • 连接建立后:主节点实时发送写命令 -> 从节点接收并执行相同命令

  • 心跳检测维持连接状态

    通常包括以下步骤及箭头表示流向:

    code
    1从节点 --> 连接主节点
    2主节点 --> 检查复制状态
    3    --> 初始同步: BGSAVE -> 发送RDB -> 发送缓冲区命令
    4或 --> 增量同步: 根据偏移量发送未接收命令
    5从节点 <-- 接收并载入RDB
    6从节点 <-- 实时接收并执行主节点发送的写命令
    7[循环] 主节点 --> 发送心跳信号 / 写命令 --> 从节点 <-- 接收并执行

    为了直观理解,建议查看相关的Redis主从复制原理流程图示例。

实例

运行三主三从,改名字,改地址,改端口号复制6个

bash
docker run -d --name redis-node-1 --net host --privileged=true -v /data/redis/share/redis-node-1:/data redis:6.2.6 --cluster-enabled yes --appendonly yes --port 6381

进入容器,构建主从关系

bash
docker exec -it redis-node-1 bash

redis-cli --cluster create 192.168.111.147:6381 192.168.111.147:6382 192.168.111.147:6383 192.168.111.147:6384 192.168.111.147:6385 192.168.111.147:6386 --cluster-replicas 1
#--cluster-replicas 1 一个主节点,一个从节点

进入redis,查看主从关系

bash
cluster info
cluster nodes

查看集群信息

bash
redis-cli --cluster check 192.168.111.147:6381

新增主节点

bash
#将新增的6387作为master节点加入集群
#redis-cli --cluster add-node 自己实际IP地址:6387 自己实际IP地址:6381
#6387 就是将要作为master新增节点

重新分配槽号

bash

#命令:redis-cli --cluster reshard IP地址:端口号
redis-cli --cluster reshard 192.168.111.147:6381

新增从节点

bash
#redis-cli --cluster add-node ip:新slave端口 ip:新master端口 --cluster-slave --cluster-master-id 新主机节点ID
 
redis-cli --cluster add-node 192.168.111.147:6388 192.168.111.147:6387 --cluster-slave --cluster-master-id e4781f644d4a4e4d4b4d107157b9ba8144631451

删除节点

bash

#redis-cli --cluster del-node ip:从机端口 从机6388节点ID
 
redis-cli --cluster del-node 192.168.111.147:6388 5d149074b7e57b802287d1797a874ed7a1a284a8
#需重新分配槽号

Released under the MIT License.