Redis学习笔记(七):主从复制

什么是主从复制

是为了解决单机状态下服务器宕机带来的风险.

主从复制可以理解为是slave节点通过不间断复制主节点的数据来实现灾难备份的手段之一,它和RDB等持久化的区别在于主从复制是运行时起作用,RDB或AOF则需要重启写入来恢复数据.

实现

比如我的6380节点希望以slave的角色作为6379节点的从属,那么可以执行

redis-cli -p 6380 slaveof 127.0.0.1 6379

也可以通过修改配置文件的方式

slaveof ip port
# 从节点只读,默认yes
slave-read-only yes

# 如果有密码,需要配置密码
masterauth XXXXXX

取消

如果想撤销自身的从节点属性,可以使用

redis-cli -p 6380 slaveof no one

此时,原master节点新增数据不会被复制,已经复制过来的数据不会被删除.

状态

一般状态查看均涉及info命令.这里列举主机(server)和分片(replication)两种信息.

  1. 主机

    redis-cli -p 6380 info server
    

    得到如下输出

    # Server
    redis_version:5.0.7
    redis_git_sha1:00000000
    redis_git_dirty:0
    redis_build_id:7e387a3dd196c136
    redis_mode:standalone
    os:Linux 4.15.0-30deepin-generic x86_64
    arch_bits:64
    multiplexing_api:epoll
    atomicvar_api:atomic-builtin
    gcc_version:6.3.0
    process_id:14424
    run_id:b702eade18c5e3cf283f6116e572761af352ef17
    tcp_port:6380
    uptime_in_seconds:1420
    uptime_in_days:0
    hz:10
    configured_hz:10
    lru_clock:1916305
    executable:/usr/local/download/redis-server
    config_file:/etc/redis/redis-6380.conf
    
  2. 分片

    redis-cli info replication
    

    得到如下输出

    # Replication
    role:slave
    master_host:127.0.0.1
    master_port:6379
    master_link_status:up
    master_last_io_seconds_ago:0
    master_sync_in_progress:0
    slave_repl_offset:2002
    slave_priority:100
    slave_read_only:1
    connected_slaves:0
    master_replid:57cc3f56c87301d65b85dac88c8564c249af7132
    master_replid2:0000000000000000000000000000000000000000
    master_repl_offset:2002
    second_repl_offset:-1
    repl_backlog_active:1
    repl_backlog_size:1048576
    repl_backlog_first_byte_offset:1
    repl_backlog_histlen:2002
    

    可以看到自身角色以及其他关联实例信息.

复制方式

主从复制,很关键的一点就是复制,那么,什么时候全量复制,什么时候增量复制呢?

全量

在刚设置master节点后,会进行全量复制。原理是,首先将master本身的RDB文件同步给slave,而在同步期间,master写入的命令也会记录下来(master内部有一个复制缓冲区,会记录同步时master新增的写入),当slaveRDB加载完后,会通过偏移量(redis-cli info replication | grep offset)的对比将这期间master写入的值同步给slave

原理
  1. slave内部首先会发送一个psync的命令给master 这个命令第一个参数是runId,第二个参数是偏移量,而由于是第一次复制,slave不知道masterrunId,也不知道自己偏移量1,这时候会传一个问号和-1,告诉master节点是第一次同步。
  2. master接受到psync ? -1时,就知道slave是要全量复制,就会将自己的runIDoffset告知slave
  3. slave会将master信息保存
  4. master这时会做一个RDB的生成(bgsave
  5. RDB发送给slave
  6. 将复制缓冲区记录的操作也发送给slave
  7. slave清空自己的所有老数据
  8. slave这时就会加载RDB文件以及复制缓冲区数据,完成同步
开销
  1. bgsave的开销,每次bgsave需要fork子进程,对内存和CPU的开销很大
  2. RDB文件网络传输的时间(网络带宽)
  3. 从节点清空数据的时间
  4. 从节点加载RDB的时间
  5. 可能的AOF重写时间(如果我们的从节点开启了AOF,则加载完RDB后会对AOF进行一个重写,保证AOF是最新的)

增量

为什么要部分复制? 在redis2.8版本之前,如果masterslave之间的网络发生了抖动连接断开,就会导致slave完全不知道master的动作,同步就会出问题,而为了保证数据一致,等网络恢复后进行一次全量复制。而全量复制的开销是很大的,redis2.8版本就提个了一个部分复制的功能。

部分复制的实现原理:

masterslave断开连接时,,master会将期间所做的操作记录到复制缓存区当中(可以看成是一个队列,其大小默认1M)。待slave重连后,slave会向master发送psync命令并传入offsetrunId (run id并不是pidslave把它保存在内存中,重启就消失),这时候,如果master发现slave传输的偏移量的值,在缓存区队列范围中,就会将从offset开始到队列结束的数据传给slave,从而达到同步,降低了使用全量复制的开销。

本节说明

本节几乎全量复制了详解redis的全量复制与部分复制,著作权归原作者吴正宇所有.

运维建议

规避全量复制

  1. 第一次全量复制不可避免,但其他情况可以避免:
    1. 小主节点: 将maxmemory设置低一些
    2. 低峰期: 比如夜间
  2. 节点运行ID不匹配
    1. 主节点重启(run_id变化)
    2. 故障转移,例如哨兵或集群
  3. 复制积压缓冲区不足
    1. 网络中断,部分复制无法满足
    2. 增大复制缓冲区配置rel_backlog_size,网络"增强".

规避复制风暴

  1. 单主节点复制风暴

    如果主节点重启,多个从节点会复制,可以将复制结构转换成下图模式

​ 虽然可以解决master重启复制风暴,但slave-1挂掉仍然存在复制风暴问题.

  1. 单机器复制风暴

    如下图:

    解决: 主节点分散到多个主机

问题

  1. 如果6380,也就是准slave节点,以前有数据,动态执行slaveof命令后,源数据还存在吗?

    答: 不存在.

  2. 如果slave节点可写(slave-read-only 设置为no),是否会同步到master节点?

    不能!

  3. redis进程重启后会发生全量复制还是部分复制?

    答:master重启时,run id会发生变化, 会发生全量复制,因为部分复制的条件之一run id已经不能满足,slave重启时会不会,这里存疑???

参考

  1. Redis的增量复制和全量复制

  1. redis-cli -p 6380 info replication中的master_repl_offset对应的值 ↩︎

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值