美文网首页
redis入门第七课:主从复制

redis入门第七课:主从复制

作者: 阿狸404 | 来源:发表于2019-05-23 14:34 被阅读0次

    1.主从复制在windows环境下的搭建

    1.1 搭建一主两从

    复制三份下载好的redis到同一个包redis下,并命名为redis6379,redis6380,redis6381,如图所示:


    1556073069(1).png

    1.2 修改redis.windows.conf配置文件

    • redis6379 中修改redis.windows.conf如下信息:
    # Accept connections on the specified port, default is 6379 (IANA #815344).
    # If port 0 is specified Redis will not listen on a TCP socket.
    port 6379
    
    • redis6380 中修改redis.windows.conf如下信息:
    # Accept connections on the specified port, default is 6379 (IANA #815344).
    # If port 0 is specified Redis will not listen on a TCP socket.
    port 6380
    slaveof 127.0.0.1 6379
    
    • redis6381 中修改redis.windows.conf如下信息:
    # Accept connections on the specified port, default is 6379 (IANA #815344).
    # If port 0 is specified Redis will not listen on a TCP socket.
    port 6381
    slaveof 127.0.0.1 6379
    

    这样我们就搭建了主服务器:127.0.0.1 6379,从服务器:127.0.0.1 6380,127.0.0.1 6380.

    1.3 启动服务器

    为了方便,我们写三个脚本来启动服务。如图所示:


    1556073323(1).png
    • start6379.bat内容如下:
    @echo off
    title redis6379
    cd redis6379
    redis-server.exe redis.windows.conf
    exit
    
    • start6380.bat内容如下:
    @echo off
    title redis6380
    cd redis6380
    redis-server.exe redis.windows.conf
    exit
    
    • start6381.bat内容如下:
    @echo off
    title redis6381
    cd redis6381
    redis-server.exe redis.windows.conf
    exit
    

    启动如下:


    master:6379.png
    slave:6380.png
    slave:6381

    1.4 测试

    开启各个redis客户端测试:

    主服务器:set msg "hello"
    如下所示:

    D:\company\redis\redis6379>redis-cli -p 6379
    127.0.0.1:6379> set msg "hello world"
    OK
    127.0.0.1:6379>
    

    从服务器获取:get msg
    如下所示:

    D:\company\redis\redis6380>redis-cli -p 6380
    127.0.0.1:6380> get msg
    "hello world"
    127.0.0.1:6380>
    
    D:\company\redis\redis6381>redis-cli -p 6381
    127.0.0.1:6381> get msg
    "hello world"
    127.0.0.1:6381>
    

    这样搭建主从复制算成功了。接下来我们详细讲解下集群。

    2. 主从复制概述

    2.1 定义

    主从复制:就是一台redis服务器B从另一台redis服务器A复制数据。我们称服务器A为主服务器,B服务器为从服务器。其中,每台从服务器只能有一台主服务器,但是一台主服务器可以有多台从服务器。
    数据的复制是单向的,只能由主服务器复制到从服务器。

    2.2 作用

    • 数据冗余
      主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
    • 故障恢复
      主从复制消除了单点故障问题,如果主服务器宕机,可以由从服务器提供服务。
    • 负载均衡
      配合读写分离,主服务器可以作为写操作,而读操作可以由从服务器提供,这样分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。

    3. 如何使用主从复制

    3.1 建立复制

    建立复制有三种方式:

    • 配置文件
      在从服务器的配置文件中加入:slaveof<masterip><masterport>
    • 启动命令
      redis-server启动命令后加入:slaveof<masterip><masterport>
    • 客户端命令
      Redis服务器启动后直接通过客户端执行命令:slaveof<masterip><masterport>,则该Redis实例成为从节点。

    3.2 断开复制

    通过slaveof<masterip><masterport>命令建立主从复制关系以后,可以通过slaveof no one断开。需要注意的是,从节点断开复制后,不会删除已有的数据,只是不再接受主节点新的数据变化。

    4. 主从复制原理

    主从复制为三个阶段:
    连接建立阶段(即准备阶段)、数据同步阶段、命令传播阶段。

    4.1 连接建立阶段

    4.2 数据同步阶段

    数据同步方式有全量复制和部分复制。

    • 全量复制
      用于初次复制或其它无法进行部分复制的情况,将主节点中的所有数据都发送给从节点,是一个非常重型的操作。
    • 部分复制
      用于网络中断等情况后的复制,只将中断期间主节点执行的写命令发送给从节点,与全量复制相比更加高效。需要注意的是,如果网络中断时间过长,造成主节点没有能够完整地保存中断期间执行的写命令,则无法进行部分复制,仍使用全量复制。
    4.2.1 全量复制
    • 全量复制流程
      全量复制过程如下:

      图片.png
    • 全量复制缺点

    1. 全量复制需要执行bgsave,fork出子线程进行rdb持久化,消耗内存,IO。
    2. 复制完之后,从服务器需要删除旧的所有数据并载入RDB文件,这个过程是阻塞的,从服务器不能提供服务。
    3. 在复制未完成之前,master/slave因为网络问题断开连接,而这个时候,master是无法得知某个命令最终
      同步给了多少个slave数据库。但是redis提供了一个配置项来限制只有数据至少同步给多少个slave的时候,master才是可写的:
      min-slaves-to-write 3 表示只有当3个或以上的slave连接到master,master才是可写的
      min-slaves-max-lag 10 表示允许slave最长失去连接的时间,如果10秒还没收到slave的响应,则master认为该slave已断开。
    4.2.2 部分复制

    当slave与master断开连接,我们需要提供一种类似断开续传的功能,在断开连接之后的部分复制。
    部分复制的实现,依赖于三个重要的概念:
    复制偏移量
    master在内存中创建一个backlog,master和slave都会保存一个复制偏移量offset,这个偏移量就是每次master如果发送N个字节数据,master的offset就会增加N,如果slave接收到这N个字节数据,并载入。则slave复制偏移量offset增加N。然后redis就通过master和slave的偏移量来判断主从服务器的状态一致性,如果不一致,就需要确定再次复制的位置(就是复制积压缓冲区)。如果master和slave网络连接断掉了,slave会让master从上次的replica offset开始继续复制,但是如果没有找到对应的offset,那么就会执行一次全量同步。

    图片.png
    比如我们前面搭建的一主两从的主从复制,这里如果主服务器的offset:900,两个从服务器A,B的分别为:offset:900,offset:900.此时主从服务器状态是一致的。
    图片.png
    现在主服务器发送100个字节数据,两个从服务器接收了,并载入。这时服务器状态是一致的。
    图片.png
    但是,现在主服务器发送100个字节数据,从服务器A断线没接收到,我们可以看到主从服务器的offset不一致了,那么在从服务器重启之后,这个数据如何恢复呢?就需要复制积压缓冲区。
    复制积压缓冲区
    复制积压缓冲区是由主服务器维护的固定长度的先进先出的队列,默认大小为1M。

    在命令传播阶段,主节点除了将写命令发送给从节点,还会发送一份给复制积压缓冲区,作为写命令的备份;除了存储写命令,复制积压缓冲区中还存储了其中的每个字节对应的复制偏移量(offset) 。由于复制积压缓冲区定长且先进先出,所以它保存的是主节点最近执行的写命令;时间较早的写命令会被挤出缓冲区。

    由于该缓冲区长度固定且有限,因此可以备份的写命令也有限,当主从节点offset的差距过大超过缓冲区长度时,将无法执行部分复制,只能执行全量复制。反过来说,为了提高网络中断时部分复制执行的概率,可以根据需要增大复制积压缓冲区的大小(通过配置repl-backlog-size)来设置;例如如果网络中断的平均时间是60s,而主节点平均每秒产生的写命令(特定协议格式)所占的字节数为100KB,则复制积压缓冲区的平均需求为6MB,保险起见,可以设置为12MB,来保证绝大多数断线情况都可以使用部分复制。

    从节点将offset发送给主节点后,主节点根据offset和缓冲区大小决定能否执行部分复制:

    • 如果offset偏移量之后的数据,仍然都在复制积压缓冲区里,则执行部分复制;

    • 如果offset偏移量之后的数据已不在复制积压缓冲区中(数据已被挤出),则执行全量复制。
      服务器运行ID
      在部分复制时,还需要用到服务器运行ID。就是说,从服务器断开之后重连的那台主服务器还是原来的主服务器吗?
      比如,原来的主从复制是这样的:

      图片.png
      但是主节点宕机重启之后,Runid会发生变化。就不能执行部分复制。
      主服务器在从服务器首次复制时,把自己自动生成40个字符的服务器运行ID发送给从服务器,如果从服务器断开重连的时候,需要把这个服务器运行ID发送给主服务器:
    • 主服务器需要比较这个服务器运行ID和自身保存的服务器ID是否一致。

    • 如果一致,则部分复制。如果不一致,则全量复制。
      整个流程如下图所示:


      图片.png

    4.3 命令传播

    数据同步完成,就进入了命令传播阶段,主要是猪服务器将写命令发送给从服务器,从服务器更新数据,从而保证主从数据的一致性。

    4.3.2 心跳机制

    在命令传播阶段,除了发送写命令,主从节点还维持着心跳机制:PING和REPLCONF ACK。心跳机制对于主从复制的超时判断、数据安全等有作用。

    6.1 主--从:PING

    在命令传播阶段,主服务器定时发送PING命令到从服务器,为了让从节点进行超时判断。。PING发送的频率由repl-ping-slave-period参数控制,单位是秒,默认值是10s

    6.1 从--主:REPLCONF ACK

    在命令传播阶段,从节点会向主节点发送REPLCONF ACK命令,频率是每秒1次;命令格式为:REPLCONF ACK{offset},其中offset指从节点保存的复制偏移量。主要有以下三个作用:

    • 检测主从服务器之间的网络连接状态
    • 检测命令丢失
    • 辅助实现min-slave选项

    相关文章

      网友评论

          本文标题:redis入门第七课:主从复制

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