• Redis——主从复制


    前言

    Redis高可用的方案包括持久化、主从复制(及读写分离)、哨兵和集群。其中持久化侧重解决的是Redis数据的单机备份问题(从内存到硬盘的备份);

    而主从复制则侧重解决数据的多机热备。此外,主从复制还可以实现负载均衡和故障恢复。

    一、主从复制概述

    主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据的复制是单向的,只能由主节点到从节点。

    默认情况下,每台Redis服务器都是主节点;且一个主节点可以有多个从节点(或没有从节点),但一个从节点只能有一个主节点。

    主从复制的作用

    1. 数据冗余:主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。
    2. 故障恢复:当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。
    3. 负载均衡:在主从复制的基础上,配合读写分离,可以由主节点提供写服务,由从节点提供读服务(即写Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。
    4. 高可用基石:除了上述作用以外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。

    二、如何使用主从复制

     为了更直观的理解主从复制,在介绍其内部原理之前,先说明我们需要如何操作才能开启主从复制。

    1. 建立复制

    需要注意,主从复制的开启,完全是在从节点发起的;不需要我们在主节点做任何事情。

    从节点开启主从复制,有3种方式:

    • (1)配置文件

    在从服务器的配置文件中加入:slaveof <masterip> <masterport>

    • (2)启动命令

    redis-server启动命令后加入 --slaveof <masterip> <masterport>

    • (3)客户端命令

    Redis服务器启动后,直接通过客户端执行命令:slaveof <masterip> <masterport>,则该Redis实例成为从节点。

    上述3种方式是等效的,下面以客户端命令的方式为例,看一下当执行了slaveof后,Redis主节点和从节点的变化。

    2. 实例

    • 准备工作:启动两个节点

    方便起见,实验所使用的主从节点是在一台机器上的不同Redis实例,其中主节点监听6379端口,从节点监听6380端口;从节点监听的端口号可以在配置文件中修改:

    启动后可以看到:

    两个Redis节点启动后(分别称为6379节点和6380节点),默认都是主节点。

    • 建立复制

    此时在6380节点执行slaveof命令,使之变为从节点:

    • 观察效果

    下面验证一下,在主从复制建立后,主节点的数据会复制到从节点中。

    (1)首先在从节点查询一个不存在的key:

    (2)然后在主节点中增加这个key:

    (3)此时在从节点中再次查询这个key,会发现主节点的操作已经同步至从节点:

    (4)然后在主节点删除这个key:

    (5)此时在从节点中再次查询这个key,会发现主节点的操作已经同步至从节点:

    3. 断开复制

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

    从节点执行slaveof no one后,打印日志如下所示;可以看出断开复制后,从节点又变回为主节点。

    主节点打印日志如下:

    三、主从复制实现原理

    主从复制过程大体可以分为3个阶段:连接建立阶段(即准备阶段)、数据同步阶段、命令传播阶段;下面分别进行介绍。

    1. 连接建立阶段

    该阶段的主要作用是在主从节点之间建立连接,为数据同步做好准备。

    • 步骤1:保存主节点信息

    从节点服务器内部维护了两个字段,即masterhost和masterport字段,用于存储主节点的ip和port信息。

    需要注意的是,slaveof是异步命令,从节点完成主节点ip和port的保存后,向发送slaveof命令的客户端直接返回OK,实际的复制操作在这之后才开始进行。

    这个过程中,可以看到从节点打印日志如下:

    • 步骤2:建立socket连接

    从节点每秒1次调用复制定时函数replicationCron(),如果发现了有主节点可以连接,便会根据主节点的ip和port,创建socket连接。如果连接成功,则:

    从节点:为该socket建立一个专门处理复制工作的文件事件处理器,负责后续的复制工作,如接收RDB文件、接收命令传播等。

    主节点:接收到从节点的socket连接后(即accept之后),为该socket创建相应的客户端状态,并将从节点看做是连接到主节点的一个客户端,后面的步骤会以从节点向主节点发送命令请求的形式来进行。

    这个过程中,从节点打印日志如下:

    • 步骤3:发送ping命令

    从节点成为主节点的客户端之后,发送ping命令进行首次请求,目的是:检查socket连接是否可用,以及主节点当前是否能够处理请求。

    从节点发送ping命令后,可能出现3种情况:

    (1)返回pong:说明socket连接正常,且主节点当前可以处理请求,复制过程继续。

    (2)超时:一定时间后从节点仍未收到主节点的回复,说明socket连接不可用,则从节点断开socket连接,并重连。

    (3)返回pong以外的结果:如果主节点返回其他结果,如正在处理超时运行的脚本,说明主节点当前无法处理命令,则从节点断开socket连接,并重连。

    在主节点返回pong情况下,从节点打印日志如下:

    • 步骤4:身份验证

    如果从节点中设置了masterauth选项,则从节点需要向主节点进行身份验证;没有设置该选项,则不需要验证。从节点进行身份验证是通过向主节点发送auth命令进行的,auth命令的参数即为配置文件中的masterauth的值。

    如果主节点设置密码的状态,与从节点masterauth的状态一致(一致是指都存在,且密码相同,或者都不存在),则身份验证通过,复制过程继续;如果不一致,则从节点断开socket连接,并重连。

    • 步骤5:发送从节点端口信息

    身份验证之后,从节点会向主节点发送其监听的端口号(前述例子中为6380),主节点将该信息保存到该从节点对应的客户端的slave_listening_port字段中;

    该端口信息除了在主节点中执行info Replication时显示以外,没有其他作用。

    2. 数据同步阶段

    主从节点之间的连接建立以后,便可以开始进行数据同步,该阶段可以理解为从节点数据的初始化。具体执行的方式是:从节点向主节点发送psync命令(Redis2.8以前是sync命令),开始同步。

    数据同步阶段是主从复制最核心的阶段,根据主从节点当前状态的不同,可以分为全量复制和部分复制,下面会有一章专门讲解这两种复制方式以及psync命令的执行过程,这里不再详述。

    需要注意的是,在数据同步阶段之前,从节点是主节点的客户端,主节点不是从节点的客户端;而到了这一阶段及以后,主从节点互为客户端。

    原因在于:在此之前,主节点只需要响应从节点的请求即可,不需要主动发请求,而在数据同步阶段和后面的命令传播阶段,主节点需要主动向从节点发送请求(如推送缓冲区中的写命令),才能完成复制。

    3. 命令传播阶段

    数据同步阶段完成后,主从节点进入命令传播阶段;在这个阶段主节点将自己执行的写命令发送给从节点,从节点接收命令并执行,从而保证主从节点数据的一致性。

    在命令传播阶段,除了发送写命令,主从节点还维持着心跳机制:PING和REPLCONF ACK。由于心跳机制的原理涉及部分复制,因此将在介绍了部分复制的相关内容后单独介绍该心跳机制。

    延迟与不一致

    需要注意的是,命令传播是异步的过程,即主节点发送写命令后并不会等待从节点的回复;因此实际上主从节点之间很难保持实时的一致性,延迟在所难免。

    数据不一致的程度,与主从节点之间的网络状况、主节点写命令的执行频率、以及主节点中的repl-disable-tcp-nodelay配置等有关。

    repl-disable-tcp-nodelay no:该配置作用于命令传播阶段,控制主节点是否禁止与从节点的TCP_NODELAY;默认no,即不禁止TCP_NODELAY。

    当设置为yes时,TCP会对包进行合并从而减少带宽,但是发送的频率会降低,从节点数据延迟增加,一致性变差;具体发送频率与Linux内核的配置有关,默认配置为40ms。

    当设置为no时,TCP会立马将主节点的数据发送给从节点,带宽增加但延迟变小。

    一般来说,只有当应用对Redis数据不一致的容忍度较高,且主从节点之间网络状况不好时,才会设置为yes;多数情况使用默认值no。

    四、应用中的问题

    1. 复制相关的配置

    这一节总结一下与复制有关的配置,说明这些配置的作用、起作用的阶段,以及配置方法等;通过了解这些配置,一方面加深对Redis复制的了解,另一方面掌握这些配置的方法,可以优化Redis的使用,少走坑。

    配置大致可以分为主节点相关配置、从节点相关配置以及与主从节点都有关的配置,下面分别说明。

    • 主从节点都有关的配置

    首先介绍最特殊的配置,它决定了该节点是主节点还是从节点:

    1)   slaveof <masterip> <masterport>:Redis启动时起作用;作用是建立复制关系,开启了该配置的Redis服务器在启动后成为从节点。该注释默认注释掉,即Redis服务器默认都是主节点。

    2)   repl-timeout 60:与各个阶段主从节点连接超时判断有关,见前面的介绍。

    • 主节点相关配置

    1)   repl-diskless-sync no:作用于全量复制阶段,控制主节点是否使用diskless复制(无盘复制)。所谓diskless复制,是指在全量复制时,主节点不再先把数据写入RDB文件,而是直接写入slave的socket中,整个过程中不涉及硬盘;diskless复制在磁盘IO很慢而网速很快时更有优势。需要注意的是,截至Redis3.0,diskless复制处于实验阶段,默认是关闭的。

    2)   repl-diskless-sync-delay 5:该配置作用于全量复制阶段,当主节点使用diskless复制时,该配置决定主节点向从节点发送之前停顿的时间,单位是秒;只有当diskless复制打开时有效,默认5s。之所以设置停顿时间,是基于以下两个考虑:(1)向slave的socket的传输一旦开始,新连接的slave只能等待当前数据传输结束,才能开始新的数据传输 (2)多个从节点有较大的概率在短时间内建立主从复制。

    3)   client-output-buffer-limit slave 256MB 64MB 60:与全量复制阶段主节点的缓冲区大小有关,见前面的介绍。

    4)   repl-disable-tcp-nodelay no:与命令传播阶段的延迟有关,见前面的介绍。

    5)   masterauth <master-password>:与连接建立阶段的身份验证有关,见前面的介绍。

    6)   repl-ping-slave-period 10:与命令传播阶段主从节点的超时判断有关,见前面的介绍。

    7)   repl-backlog-size 1mb:复制积压缓冲区的大小,见前面的介绍。

    8)   repl-backlog-ttl 3600:当主节点没有从节点时,复制积压缓冲区保留的时间,这样当断开的从节点重新连进来时,可以进行部分复制;默认3600s。如果设置为0,则永远不会释放复制积压缓冲区。

    9)   min-slaves-to-write 3与min-slaves-max-lag 10:规定了主节点的最小从节点数目,及对应的最大延迟,见前面的介绍。

    • 从节点相关配置

    1)   slave-serve-stale-data yes:与从节点数据陈旧时是否响应客户端命令有关,见前面的介绍。

    2)   slave-read-only yes:从节点是否只读;默认是只读的。由于从节点开启写操作容易导致主从节点的数据不一致,因此该配置尽量不要修改。

    2. info Replication

    在Redis客户端通过info Replication可以查看与复制相关的状态,对于了解主从节点的当前状态,以及解决出现的问题都会有帮助。

    主节点:

    从节点:

    对于从节点,上半部分展示的是其作为从节点的状态,从connectd_slaves开始,展示的是其作为潜在的主节点的状态。

    五、总结

    主从复制虽然解决或缓解了数据冗余、故障恢复、读负载均衡等问题,但其缺陷仍很明显:故障恢复无法自动化;写操作无法负载均衡;存储能力受到单机的限制;

    这些问题的解决,需要哨兵和集群的帮助。

    转载:https://www.cnblogs.com/kismetv/p/9236731.html

  • 相关阅读:
    2017年0406------如何使用sessionStroage来储存参数是对象的,以及localStorage和sessionStorage的不同地方
    json格式和对象类型的转换20170330
    严重报错: Error configuring application listener of class org.springframework.web.context.ContextLoaderLis
    201703-28工作笔记:复杂的背景问题
    @Inject
    @Controller
    Mybatis
    Mybatis P2 总结
    小结--limit注入
    小结--order by 注入
  • 原文地址:https://www.cnblogs.com/caoweixiong/p/14241977.html
Copyright © 2020-2023  润新知