Redis: 主从复制原理

主从复制原理剖析


1 )配置

  • 通过下面的从节点的配置项可以开启主从之间的复制功能
    slaveof 192.16.10.101 6379
    
  • 这里的复制包含全量复制和增量复制

2 )主节点的主从配置信息解析

  • 查看主从之间的信息,在主节点上 $ info replication 打印出来的细节
    # Replication
    role: master
    connected_slaves: 2
    slave0:ip=192.168.10.102,port=6379,state=online,offset=2184,lag=1
    slave1:ip=192.168.10.103,port=6379,state=online,offset=2184,lag=1
    master_replid:0e233bbb3b38aada4764b58c2dc9e74ddfc85ccc
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:2184
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen: 2184
    
    • 从节点 offset 是指读取命令的偏移量
      • 相当于: 从节点现在已复制的偏移量的长度
      • 主节点实际上会把所有的命令转成字节,然后写到一个队列里边
      • 然后它写入了多少会记录下最终的值,也就是对应下面的 master_repl_offset
      • 两者相等,表示主从数据一致
    • lag 延迟时间,lag=1 延迟时间是1s,主从同步数据会有延迟
    • master_repl_offset 主节点已写入的命令偏移量
    • master_replid 和 master_replid2
      • master_replid 表示主节点的一个 replicationID, 它是40个16进制的字符串,随机生成的
      • master_replid2
        • 表示主节点的状态发生改变之后
        • 新的主节点ID会存放在 master_replid 中
        • 旧的主节点ID会存放在 master_replid2 中
    • 下面的5项都是在 Redis 2.8 之后, 出现的特性
      • 这里既然涉及到了主从复制,肯定会有一个全量复制,增量复制这样一个概念在里边
      • 全量复制是指:从节点把主节点的数据据全部都拷贝过去
      • 这种一般发生在环境初始化和从节点扩展以及主节点故障在从节点选举新的主节点场景中
      • 在主节点故障重新选举的过程中,run_id 会出现变化, 在 $ info server 命令中就有这个 run_id
      • 从节点根据这个 run_id 来判断是全量复制还是增量复制
    • 在2.8版本之后出现 second_repl_offset 这个配置,还有一个缓冲区的概念
    • 关于 second_repl_offset 这个配置
      • 2.8 之后,全量增量复制多了一个命令,叫 psync, 之前是建立一个 sync 的操作
      • 比如说, 现在主节点故障重启之后,它发现 run_id 变了,二话不说,走一个全量复制
      • 再有,比如说,主节点故障了,重新选取主节点,会把上一次主节点已写入队列的偏移量 master_repl_offset 记录下来,寄存到这个 second_repl_offset
      • 比如现在 master_repl_offset 已经是 2590 了,在存的时候 second_repl_offset 一般做一个 +1 的操作,也就是变成了 2591,这样,从节点再重新跟主节点建立连接的时候,会拿到这个 second_repl_offset
      • 根据上面的情况 second_repl_offset 比 master_repl_offset 多了一个字节,就没有必要做全量复制了
      • 只需要继续保持现状,跟它持续连接,每十秒 ping 一下,监听着它就行了, 继续做增量操作
      • 所以,second_repl_offset 的作用就是为了避免每一次主从的角色改变/故障重启等场景带来可能的全量复制操作而浪费性能,这样增量操作就能解决问题
    • 关于缓冲区的配置
      • repl_backlog_active: 1 表示缓冲区开启
      • repl_backlog_size:1048576 表示缓冲区的大小, 这里是 1M的大小
      • repl_backlog_first_byte_offset:1 表示从1的位置开始写
      • repl_backlog_histlen: 2184 表示当前缓冲区的长度

3 )从节点的主从配置信息解析

  • 在从节点上 $ info replication 打印出来的细节
    # Replication
    role:slave
    master_host:192.168.10.101
    master_port:6379
    master_link_status:up
    master_last_io_seconds_ago:5
    master_sync_in_progress:0
    slave_repl_offset:2842
    slave_priority:100
    slave_read_only:1
    connected_slaves:0
    master_replid:0e233bbb3b38aada4764b58c2dc9e74ddfc85ccc
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:2842
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen:2842
    
  • 上面 master_* 是主节点的一系列信息,主要看下
    • master_last_io_seconds_ago:5 表示从库和主库最后一次同步数据的时间在五秒之前
    • master_sync_in_progress:0 表示和主库的同步状态,0是未同步,1是正在同步
    • master_repl_offset:2842 表示主节点写入的偏移量
  • 上面 slave_* 是从节点的一些列配置
    • slave_repl_offset 表示从节点复制的偏移量,和上面主节点写入偏移量一致,说明同步了
    • slave_priority:100 表示从节点在选举时成为主节点的一个几率
      • 比如主节点宕机,剩下的2个从节点开始参与选举
      • 谁能竞选成功,就看上面这个数值的大小,越大则优先级越高,竞选越容易成功
      • 如果这个值为 0,则这个从节点永远不会变成主节点
    • slave_read_only:1 从节点只读模式,1表示开启,0表示关闭
  • connected_slaves:0 表示连接到从节点的信息
    • 作为从节点,也是可以去连其他的从节点的
  • 其他选项不再赘述

4 ) Master复制日志查看

  • master/slave 进行主从进行复制的时候,在日志中也是可以体现出来

  • 下面通过查看日志的方式,把主从的一个复制流程走一遍

  • 在主节点查看日志:$ tail -f -n 800 /usr/local/redis/log/redis.log, 我们从下面位置来看

    l. This will create latency and memory usage issues with Redis. To fix this issue run the command 'echo madvi
    se > /sys/kernel/mm/transparent hugepage/enabled' as root, and add it to your /etc/rc. local in order to retai
    n the setting after a reboot. Redis must be restarted after THP is disabled (set to 'madvise' or 'never').
    1468:M 1 Oct 2020 14:21:15.520 * DB loaded from append only file: 0.000 seconds
    1468:M 1 Oct 2020 14:21:15.520 * Ready to accept connections
    1468:M 1 Oct 2020 14:21:28.323 * Replica 192.168.10.102:6379 asks for synchronization
    1468:M 1 Oct 2020 14:21:28.324 * Full resync requested by replica 192.168.10.102:6379
    1468:M 1 Oct 2020 14:21:28.324 * Replication backlog created, my new replication IDs are '0e233bbb3b38aada47
    64b58c2dc9e74ddfc85ccc'and '0000000000000000000000000000000000000000'
    1468:M 1 Oct 2020 14:21:28.324 * Starting BGSAVE for SYNC with target: disk
    1468:M 1 Oct 2020 14:21:28.324 * Background saving started by pid 1474
    1474:C 1 Oct 2020 14:21:28.326 * DB saved on disk
    1474:C 1 Oct 2020 14:21:28.326 * RDB: 4 MB of memory used by copy-on-write
    1468:M 1 Oct 2020 14:21:28.332 * Background saving terminated with success
    1468:M 1 Oct 2020 14:21:28.332 * Synchronization with replica 192.168.10.102:6379 succeeded
    1468:M 1 Oct 2020 14:21:30.858 * Replica 192.168.10.103:6379 asks for synchronization
    1468:M 1 Oct 2020 14:21:30.858 * Full resync requested by replica 192.168.10.103:6379
    1468:M 1 Oct 2020 14:21:30.858 * Starting BGSAVE for SYNC with target: disk
    1468:M 1 Oct 2020 14:21:30.859 * Background saving started by pid 1475
    1475:C 1 Oct 2020 14:21:30.861 * DB saved on disk
    1475:C 1 Oct 2020 14:21:30.861 * RDB: 4 MB of memory used by copy-on-write
    1468:M 1 Oct 2020 14:21:30.952 * Background saving terminated with success
    1468:M 1 Oct 2020 14:21:30.952 * Synchronization with replica 192.168.10.103:6379 succeeded
    
  • Ready to accept connections 表示随时等待其他节点的连接

  • Replica 192.168.10.102:6379 asks for synchronization 表示 102 从节点开始过来复制了

    • 这里可见,它发起了 sync 的请求
  • Full resync requested by replica 192.168.10.102:6379 表示 102 的复制请求是全量的复制请求

  • Replication backlog created, my new replication IDs are '0e233bbb3b38aada4764b58c2dc9e74ddfc85ccc'and '0000000000000000000000000000000000000000'

    • 刚把环境起起来,这里主节点开始创建缓冲区并生成新的 replication IDs
    • 这里有2个ID,就是上文说的 master_replid 和 master_replid2
  • 下面是RDB的操作

    1468:M 10 Nov 2020 14:21:28.324 * Starting BGSAVE for SYNC with target: disk
    1468:M 10 Nov 2020 14:21:28.324*  Background saving started by pid 1474
    1474:C 10 Nov 2020 14:21:28.326 * DB saved on disk
    1474:C 10 Nov 2020 14:21:28.326 * RDB: 4 MB of memory used by copy-on-write
    1468:M 10 Nov 2020 14:21:28.332 * Background saving terminated with success
    
    • 首先,通过 BGSAVE 把数据写入磁盘,可以看到它是后台的写入进程
    • 之后,通过 copy-on-write 把内存的 4M 数据写入磁盘
    • 最后,保存结束,终止
  • Synchronization with replica 192.168.10.102:6379 succeeded

    • 这里,提示 102 机器的复制成功了
  • 下面是 103 重复RDB的复制操作

    1468:M 10 Nov 2020 14:21:30.858 * Replica 192.168.10.103:6379 asks for synchronization
    1468:M 10 Nov 2020 14:21:30.858 * Full resync requested by replica 192.168.10.103:6379
    1468: M 10 Nov 2020 14:21:30.858 * Starting BGSAVE for SYNC with target: disk
    1468:M 10 Nov 2020 14:21:30.859 * Background saving started by pid 1475
    1475:C 10 Nov 2020 14:21:30.861 * DB saved on disk
    1475:C 10 Nov 2020 14:21:30.861 * RDB: 4 MB of memory used by copy-on-write
    1468:M 10 Nov 2020 14:21:30.952 * Background saving terminated with success
    1468:M 10 Nov 2020 14:21:30.952 * Synchronization with replica 192.168.10.103:6379 succeeded
    
    • 不再赘述

5 )画图来看复制流程(全量复制)

  • 环境搭建好之后,slave节点就发起了一个 sync 的请求,这个请求是一个 全量复制
    • 其实增量无非就是在环境构建完成之后,每次你写入一个,我就复制一个写入一个复制一个
  • sync 的命令到主节点,主节点这边执行 BGSAVE 执行BGsave之后,生成RDB快照
  • 然后,主节点会把RDB的快照发送给 slave 节点
  • slave 节点拿到RDB快照之后,会把它节点上旧的数据全部删掉,加载RDB的文件
  • 在上述过程中,我们看下
    • master主节点,在执行 BGSAVE 的时候,它是一个非阻塞的
    • 就是说, 在生成RDB执行BGSAVE 期间, 仍然是可以对外提供服务的
    • 也就是说它仍然是可以读写的,如果说这时候有一些命令,它就会把命令写到缓冲区里边去
    • 就是我们的backlog里边,它为什么要这么做呢?
    • 一方面,为了提高性能,无阻塞可提供反馈
    • 另一方面,写到缓冲区里边,master 已经生成RDB快照发给 slave节点了
    • 后续的命令从节点就拿不到了,所以,给它放到这个缓冲区里边
    • 等 slave 这边RDB加载完之后,它再从缓冲区里边去拿走后续的那些命令
    • 相当于就是把整个的数据全部复制过去了
  • 所以,我们的 slave 除了加载 RDB 之外,它还会去缓冲区里边继续接受这些命令,最终完成一个init
  • 所以,这里面包含:RDB的加载完成和缓冲区命令的复制都完成了

6 )再来看下增量复制

  • 增量复制更多的是 Slave 初始化完成后,环境已经稳定了,这个时候,就会做增量的复制
  • 增量复制就是主服务器那边发生了写操作,它就会同步到从服务器的一个过程
  • 复制的过程就是
    • 主服务器执行一个命令,从服务器就会发送一个相同的写命令
    • 从服务器接收到之后就开始执行
  • 我们可以演示一下
    • 在从服务器中执行 $ sync 先建立连接
    • 在主服务器中,进行写操作 $ set age 18
    • 在从服务器终端中输入
      "PING"
      "SELECT","0"
      "set","age","18"
      "PING"
      
      • 可以看到,每10s就会PING一下,得到新的同步的命令这样保持心跳
  • 在2.8之前都是全量复制,之后便可以增量复制了

7 )主从复制的异步性

  • 主从复制这个过程,主节点是非阻塞的,在复制的这个流程中
  • 它是开启的一个后台子守护进程去做这件事情的,比如 BGSAVE 和 生成 RDB快照发送等
  • 当前服务器仍然是可以对外提供读写这样的一些请求的,这个就是非阻塞,体现异步性
  • 从节点也是一样的,比如说正在复制主节点的数据,这个SYNC的操作也是非阻塞的
  • 复制的过程中, 它可能就会有一点问题, 比如,正在复制时,一个查询过来
    • 那我可能查到的就是比如说一些老数据,这里边就会有脏读,数据不一致等等的问题
    • 这块在故障解决中有一些方案来处理

8 )过期 key 的处理

  • 实际上从节点是不会让 key 过期的,从节点它没有 key 过期的概念
  • 它会等待接收主节点delete的命令,可以看下面的演示
    • 从节点:$ sync 先监控下
    • 主节点:$ set age 18 ex 10
    • 查看从节点输出
      "PING"
      "set","age","18","ex","10"
      "PING"
      "DEL","age"
      "PING"
      
      • 可以看到,它在等主节点发DEL 命令
  • 也就是,当Master让key到期时,会合成一个 DEL 命令传输到所有 Slave

9 )加速复制

  • 上面看日志可知,每一次的复制都会生成RDB,然后把RDB的快照文件发给从节点
  • 如果说你的磁盘性能比较差,每一次的主从复制都要写入磁盘,如后再生成RDB文件发送给从节点,性能就会被降低,因为磁盘性能差
  • 可以不写入磁盘,直接生成RDB文件发给从节点就可以了,在 Redis@2.8.18这个版本之后,加入了这个功能,可以设置无需写入磁盘,直接把这个RDB的快照文件发给从节点
  • 修改配置:repl-diskless-sync yes 默认值是 no 不开启
    • 不开启的情况下,BGSAVE 先写磁盘,然后把生成RDB快照再发送
    • 设置为 yes 开启之后,就直接把RDB快照发给从节点
    • 不会写磁盘操作,这样就加速了复制
Redis主从复制是一种数据同步机制,用于将一个Redis服务器的数据复制到其他Redis服务器上。在主从复制机制中,一个Redis服务器充当主服务器(master),而其他Redis服务器则充当从服务器(slave)。 主从复制原理如下: 1. 从服务器连接到主服务器并发送SYNC命令请求同步数据。 2. 主服务器收到SYNC命令后开始执行BGSAVE命令,将当前内存中的数据保存到磁盘上。 3. 当BGSAVE命令执行完毕后,主服务器将生成一个RDB文件,并将该文件发送给从服务器。 4. 从服务器接收到RDB文件后,将其加载到内存中,并执行主服务器自上次保存快照之后执行的所有写命令(即增量复制)。 5. 从服务器在与主服务器的连接断开后,会自动重新连接并继续执行增量复制。 需要注意的是,主从复制是异步的,从服务器并不会立即复制主服务器上的所有数据,而是在主服务器执行写操作后异步地进行复制。这种异步复制的特性使得主从复制可以在不影响主服务器性能的情况下进行数据同步。 主从复制的优点在于: 1. 提高数据可用性:主从复制可以在主服务器故障时快速地将从服务器提升为主服务器,从而提高数据的可用性。 2. 分担主服务器负载:通过将读请求转发到从服务器,可以分担主服务器的负载,提高整个系统的性能。 3. 数据备份:通过将数据复制到多个从服务器上,可以提高数据的备份和恢复能力。 需要注意的是,主从复制并不能保证数据的强一致性,因此在使用主从复制时需要注意数据的一致性问题。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值