美文网首页
Redis主从复制

Redis主从复制

作者: 若兮缘 | 来源:发表于2019-03-28 22:31 被阅读0次

    单机有什么问题?

    单机即在一台机器上部署一个redis节点,主要会存在以下问题:

    1. 机器故障

    如果发生机器故障,例如磁盘损坏,主板损坏等,未能在短时间内修复好,客户端将无法连接redis。
    当然如果仅仅是redis节点挂掉了,可以进行问题排查然后重启,姑且不考虑这段时间对外服务的可用性,那还是可以接受的。
    而发生机器故障,基本是无济于事。除非把redis迁移到另一台机器上,并且还要考虑数据同步的问题。

    2. 容量瓶颈

    假如一台机器是16G内存,redis使用了12G内存,而其他应用还需要使用内存,假设我们总共需要60G内存要如何去做呢,是否有必要购买64G内存的机器?

    3. QPS瓶颈

    redis官方数据显示可以达到10w的QPS,如果业务需要100w的QPS怎么去做呢?

    关于容量瓶颈和QPS瓶颈是redis分布式需要解决的问题,而机器故障就是高可用的问题了。

    主从复制的作用

    一主一从

    如图所示左边是Master节点,右边是slave节点,即主节点和从节点。从节点也是可以对外提供服务的,主节点是有数据的,从节点可以通过复制操作将主节点的数据同步过来,并且随着主节点数据不断写入,从节点数据也会做同步的更新。
    整体起到的就是数据备份的效果。

    一主多从

    除了一主一从模型之外,redis还提供了一主多从的模型,也就是一个master可以有多个slave,也就相当于有了多份的数据副本。
    这样可以做一个更加高可用的选择,例如一个master和一个slave挂掉了,还能有其他的slave数据备份。

    读写分离

    除了作为数据备份,主从模型还能做另外一个功能,就是读写分离。
    让master节点负责提供写服务,而将数据读取的压力进行分流和负载,分摊给所有的从节点。

    主从复制的作用
    1. 数据副本(备份)
    2. 扩展读性能(读写分离)
    简单总结
    1. 一个master可以有多个slave
    2. 一个slave只能有一个master
    3. 数据流向是单向的,master到slave

    主从复制的配置

    1. slaveof命令

    如图,想让6380节点成为6379的从节点,只需要执行 slaveof 命令即可,此复制命令是异步进行的,redis会自动进行后续数据复制的操作。
    注:一般生产环境不允许主从节点都在一台机器上,因为没有任何的价值。

    取消复制

    如果6380节点不希望成为6379的从节点,可以执行 slave of on one 命令,取消后6380节点的数据不会被清除,只是说后续6379节点新写入的数据不会再同步到该节点了。
    注意:如果取消复制后想slave一个新的主节点,新的主节点在同步给slave节点数据时,会先将从节点的数据全部清除

    2. 修改配置
    # 配置主节点的IP和端口号
    slaveof ip port
     # 从节点只做读的操作,保证主从数据的一致性
    slave-read-only yes 
    
    对比

    runid和复制偏移量

    redis每次启动的时候都会有一个随机的ID,作为一个标识,这个ID就是runid,当然重启之后值就改变了。
    查看runid:redis-cli -p 6379 info | grep run
    假如端口为6380的redis去复制6379,知道runid后,在6380上做一个标识,如果runid改变了,说明主可能重启了或者发生了其它变化,这时候就可以做一个全量复制把数据同步过来。或者第一次启动时根本不知道6379的runid,也会进行全量复制

    偏移量:数据写入量的字节
    比如主执行set hello world,就会有一个偏移量,然后从同步数据,也会记录一个偏移量
    当两个偏移量达到一致时候,实际上数据就是完全同步的状态。

    启动主从redis,并在写入命令执行前后查看主偏移量:
    redis-cli -p 6379 info replication | grep master_repl

    从节点会向主节点做一个上报,把从节点的状态同步给主节点,这样主节点就知道了从节点的偏移量

    生产环境我们一般不关心这个值,有时候做监控的时候会比对一下这两个值的差,如果差的太多,说明主从是有问题的。

    全量复制

    全量复制主节点会将RDB文件也就是当前状态去同步给slave,在此期间主新写入的命令会单独记录起来,然后当RDB文件加载完毕之后,会通过偏移量对比将这个期间产生的写入值同步给slave,这样就能达到数据完全同步的效果

    全量复制过程
    1. 在其内部有一条命令psync,是做同步的命令,它可以完成全量复制和部分复制的功能,当启动slave节点时,它会发送psync命令给主节点,需要传递两个参数,runidoffset(偏移量),也就是从向主传递主节点的runid以及自己的偏移量,对于第一次复制而言,就直接传递?和 -1,当然这个参数是由slave内部传的。
    2. master接收到命令后知道从希望做全量复制,主就会将自己的runid和offset传递给从
    3. slave节点保存master的基本信息
    4. master执行bgsave生成RDB文件,并且在此期间新产生的写入命令会被记录到repl_back_buffer(复制缓冲区)
    5. 主向从传输RDB文件
    6. 主向从发送复制缓冲区内容
    7. 清空从节点旧的数据
    8. 从节点加载RDB文件到内存中,同时加载缓冲区数据
    全量复制的开销

    实际上全量复制的开销是非常大的,主要体现在如下方面

    1. bgsave时间(对cpu、 内存、硬盘都会有一定的开销)
    2. RDB文件网络传输时间(网络带宽)
    3. 从节点清空数据时间(根据从节点的数据规模)
    4. 从节点加载RDB的时间
    5. 可能的AOF重写时间(在最后从加载完RDB之后如果开启了AOF,会做AOF重写)

    全量复制除了上述开销之外,还会有个问题:
    假如master和slave网络发生了抖动,那一段时间内这些数据就会丢失,对于slave来说这段时间master更新的数据是不知道的。最简单的方式就是再做一次全量复制,从而获取到最新的数据,在redis2.8之前是这么做的。

    部分复制

    部分复制,redis2.8之后提供。如果发生类似抖动时候,可以有一种机制将这种损失降低到最低,如何实现的?

    1. 如果发生了抖动,相当于连接断开了
    2. 主会将写命令记录到缓冲区,repl_back_buffer
    3. 当slave再次去连接master时候,就是说网络抖动结束之后,会触发增量复制
    4. 从会执行pysnc命令,将当前自己的offset和主的runid传递给master
    5. 如果发现传输的offset偏移量是在buffer内的,不在期间内就证明你已经错过了很多数据,buffer也是有限的,默认是1M,会将offset开始到队列结束的数据同步给从。这样master和slave就达到了一致。

    通过部分复制(增量复制)有效的降低了全量复制的开销。

    复制的相关配置

    无磁盘化复制
    # 开启无磁盘化复制
    repl-diskless-sync yes
    # 当收到第一个复制请求时,等待 5s 后再开始复制,因为要等更多 slave 一起连接过来
    repl-diskless-sync-delay 5
    
    复制的限制

    如果在复制期间,rdb复制时间超过60秒,内存缓冲区持续消耗超过64MB,或者一次性超过256MB,那么将会停止复制(失败)
    配置项:client-output-buffer-limit slave 256MB 64MB 60

    `

    相关文章

      网友评论

          本文标题:Redis主从复制

          本文链接:https://www.haomeiwen.com/subject/cwdhbqtx.html