精华内容
下载资源
问答
  • Redis主从复制的原理

    千次阅读 2019-05-28 08:00:00
    Redis集群中,让若干个Redis服务器去复制另一个Redis服务器,我们定义被复制的服务器为主服务器(master),而对主服务器进行复制...主从复制的作用 为数据提供多个副本,实现高可用 实现读写分离(主节点...

    在Redis集群中,让若干个Redis服务器去复制另一个Redis服务器,我们定义被复制的服务器为主服务器(master),而对主服务器进行复制的服务器则被称为从服务器(slave),这种模式叫做主从复制模式。

    数据流向是单向的,只能是从master到slave

    一个slave只能有一个master

    主从复制的作用

    • 为数据提供多个副本,实现高可用

    • 实现读写分离(主节点负责写数据,从节点负责读数据,主节点定期把数据同步到从节点保证数据的一致性)

    主从复制的方式

    • 命令slaveof。
      优点:无需重启。缺点:不便于管理

       

    • 
       
      // 命令行使用	
      slaveof ip port // 使用命令后自身数据会被清空,但取消slave只是停止复制,并不清空
    • 修改配置。
      优点:统一配置。缺点:需要重启

       

    • 
       
      // 配置文件中配置	
      slaveof ip port	
      slave-read-only yes //只允许从节点进行读操作

    全量复制

    用于初次复制或其它无法进行部分复制的情况,将主节点中的所有数据都发送给从节点,是一个非常重型的操作,当数据量较大时,会对主从节点和网络造成很大的开销

    640?wx_fmt=png

    全量复制过程:

    1. Redis内部会发出一个同步命令,刚开始是Psync命令,Psync ? -1表示要求master主机同步数据

    2. 主机会向从机发送run_id和offset,因为slave并没有对应的 offset,所以是全量复制

    3. 从机slave会保存主机master的基本信息

    4. 主节点收到全量复制的命令后,执行bgsave(异步执行),在后台生成RDB文件(快照),并使用一个缓冲区(称为复制缓冲区)记录从现在开始执行的所有写命令

    5. 主机发送RDB文件给从机

    6. 发送缓冲区数据

    7. 刷新旧的数据。从节点在载入主节点的数据之前要先将老数据清除

    8. 加载RDB文件将数据库状态更新至主节点执行bgsave时的数据库状态和缓冲区数据的加载。

    全量复制开销

    • 主节点需要bgsave

    • RDB文件网络传输占用网络io

    • 从节点要清空数据

    • 从节点加载RDB

    • 全量复制会触发从节点AOF重写

    部分复制

    部分复制是Redis 2.8以后出现的,用于处理在主从复制中因网络闪断等原因造成的数据丢失场景,当从节点再次连上主节点后,如果条件允许,主节点会补发丢失数据给从节点。因为补发的数据远远小于全量数据,可以有效避免全量复制的过高开销,需要注意的是,如果网络中断时间过长,造成主节点没有能够完整地保存中断期间执行的写命令,则无法进行部分复制,仍使用全量复制

    640?wx_fmt=png

    部分复制过程:

    1. 如果网络抖动(连接断开 connection lost)

    2. 主机master 还是会写 repl_back_buffer(复制缓冲区)

    3. 从机slave 会继续尝试连接主机

    4. 从机slave 会把自己当前 run_id 和偏移量传输给主机 master,并且执行 pysnc 命令同步

    5. 如果master发现你的偏移量是在缓冲区的范围内,就会返回 continue命令

    6. 同步了offset的部分数据,所以部分复制的基础就是偏移量 offset。

    服务器运行ID(run_id):每个Redis节点(无论主从),在启动时都会自动生成一个随机ID(每次启动都不一样),由40个随机的十六进制字符组成;run_id用来唯一识别一个Redis节点。 通过info server命令,可以查看节点的run_id。

    Redis复制的核心机制

    1. Redis采用异步方式复制数据到slave节点。从Redis2.8开始,slave节点会周期性地确认每次复制的数据量。
    2. 一个master节点是可以配置多个slave节点的。
    3. slave节点做复制的时候,是不会block master节点的正常工作的。
    4. slave节点在做复制的时候,也不会block对自己的查询操作,它会用旧的数据集来提供服务; 但是复制完成的时候,需要删除旧数据集,加载新数据集,这个时候就会暂停对外服务了。
    5. slave节点主要用来进行横向扩容,做读写分离,扩容的slave节点可以提高读的吞吐量。

     

    开发运维常见的问题

    1. 读写分离

    • 复制数据存在延迟(如果从节点发生阻塞)

    • 从节点可能发生故障

    1. 主从配置不一致

    • 例如maxmemory不一致,可能会造成丢失数据

    • 例如数据结构优化参数不一致:造成主从内存不一致

    1. 规避全量复制

    • 第一次全量复制不可避免,所以分片的maxmemory减小,同时选择在低峰(夜间)时,做全量复制。

    • 复制积压缓冲区不足 增大复制缓冲区配置rel_backlog_size

    例如:如果网络中断的平均时间是60s,而主节点平均每秒产生的写命令(特定协议格式)所占的字节数为100KB,则复制积压缓冲区的平均需求为6MB,保险起见,可以设置为12MB,来保证绝大多数断线情况都可以使用部分复制。

    1. 复制风暴 master节点重启,master节点生成一份rdb文件,但是要给所有从节点发送rdb文件。对cpu,内存,带宽都造成很大的压力

     

    展开全文
  • Redis主从复制的原理

    作为一个一主多从这样的一个结构设计,那么他的数据同步是非常一个重要的点。而Redis的同步设计可以分成全量同步和增量同步

    全量同步

    全量同步发生在Slave初始化的时候,也就是如上图:1-1和1第一次建立连接,1-2和1-1第一次建立连接的时候就会发送PSYNC命令:

    这个命令过程如下:

    主服务器执行BGSAVE命令-->生成RDB快照文件-->向从服务器发送RDB文件并且记录写命令-->从服务器收到后把自己原先的数据全丢了载入快照文件的数据-->载入完成后在执行记录的写命令写入到缓存里面。

     

    增量同步

    增量同步时Salve初始化后正常运行过程中,只要主服务器执行了一个写的命令,那么主服务器就和向从服务器发送一个一模一样的写命令,将数据写入缓存。

     

    部分增量同步:

    在Redis 2.8之前时SYNC的命令,这个命令时没有增量同步的,不管是什么环节,也就是每次都是全量同步,比较消耗资源,而且效率不高,并且到了如果数据量大的话,突然有个Salve宕机后重新连接,就会和多个服务器进行连接同步数据,可能会导致IO剧增宕机。

     

    在2.8后呢就优化成使用PSYNC命令了,只有服务器初始化的时候全量同步,之后正常运行过程中都是增量同步。并且在这个过程中会维护主从服务器的偏移量和ID,如果这时候有个Slave宕机重新连接,会判断这个重新连接的服务器和主服务器是否时同一个ID,如果相同,就会找到主服务器的和从服务器的偏移量的位置,也就是上次宕机断开的点继续复制后面的数据。

     

     

    展开全文
  • 一、主从复制的概念 redis为了高可用,会把数据复制到多个副本,部署到其他节点上。通过复制,实现redis的高可用性,实现对数据的冗余备份保证数据和服务的可靠性。 数据的复制是单向的,只能由master节点到slave...

    一、主从复制的概念

    redis为了高可用,会把数据复制到多个副本,部署到其他节点上。通过复制,实现redis的高可用性,实现对数据的冗余备份保证数据和服务的可靠性。
    数据的复制是单向的,只能由master节点到slave节点。下图描述了一个简单的主从复制架构。
    在这里插入图片描述
    主从复制的作用
    1)数据冗余
    主从复制实现了数据的热备份,是持久化之外的一种数据冗余方式。

    2)故障恢复
    当主节点出现问题时,可以由从节点提供服务,实现快速的故障恢复;实际上是一种服务的冗余。

    3)负载均衡
    在主从复制的基础上,配合读写分离,可以由主节点提供写服务,从节点提供读服务(即写在Redis数据时应用连接主节点,读Redis数据时应用连接从节点),分担服务器负载;尤其是在写少读多的场景下,通过多个从节点分担读负载,可以大大提高Redis服务器的并发量。

    4)读写分离
    可以用于读写分离,主库写、从库读,读写分离不仅可以提高服务器的负载能力,同时可根据需求的变化,改变从库的数量。

    5)高可用基石
    除了上述4点作用外,主从复制还是哨兵和集群能够实施的基础,因此说主从复制是Redis高可用的基础。


    二、主从复制机制

    Redis的主从复制功能除了支持一个Master节点对应多个Slave节点的同时进行复制外,还支持Slave节点向其它多个Slave节点进行复制。这样就使得架构师能够灵活组织业务缓存数据的传播,例如使用多个Slave作为数据读取服务的同时,专门使用一个Slave节点为流式分析工具服务。
    Redis的主从复制功能分为两种数据同步模式进行:全量数据同步和增量数据同步。

    1、全量数据同步
    在这里插入图片描述
    上图简要说明了Redis中Master节点到Slave节点的全量数据同步过程。

    什么时候进行全量同步?
    1)当Slave节点给定的replication id和Master的replication id不一致时;
    2)或者Slave给定的上一次增量同步的offset的位置在Master的环形内存中(replication backlog)无法定位时
    Master就会对Slave发起全量同步操作

    全量同步的时候,无论是否在Master打开了RDB快照功能,它和Slave节点的每一次全量同步操作过程都会更新/创建Master上的RDB文件。
    在Slave连接到Master,并完成第一次全量数据同步后,接下来Master到Slave的数据同步过程一般就是增量同步形式了(也称为部分同步)。增量同步过程不再主要依赖RDB文件,Master会将新产生的数据变化操作存放在replication backlog这个内存缓存区,这个内存区域是一个环形缓冲区,也就是说是一个FIFO的队列。

    特点:

    • 主节点通过BGSAVE命令fork子进程进行RDB持久化,该过程是非常消耗CPU、内存(页表复制)、硬盘IO。
    • 主节点通过网络将RDB文件发送给从节点,对主节点的带宽都会带来很大的消耗。
    • 从节点清空数据、载入新RDB文件的过程是阻塞的,无法响应客户端的命令;如果从节点执行bgrewriteaof,也会带来额外的消耗。

    2、增量数据同步
    Redis2.8开始提供部分复制,用于处理网络中断时的数据同步。
    进行增量同步 — master作为一个普通的client连入slave,将所有写操作转发给slave,没有特殊的同步协议。具体过程如下:
    在这里插入图片描述

    :为什么在Master上新增的数据除了根据Master节点上RDB或者AOF的设置进行日志文件更新外,还会同
    时将数据变化写入一个环形内存结构(replication backlog),并以后者为依据进行Slave节点的增量更新呢?主要原因有以下几个:
    1)由于网络的不稳定,网络抖动/延迟都可能造成slave和master暂时断开连接,这种情况远多于新的slave连接到master的情况。如果以上所有情况都使用全量更新,就会大大增加master的负载压力–写RDB文件是有大量I/O过程的,虽然Linux Page Cache特性会减少性能消耗。
    2)另外在数据量达到一定规模的情况下,使⽤全量更新进行和Slave的第一次同步是一个不得已的选择–因为要尽快减少Slave节点和Master节点的数据差异。所以只能占用Master节点的资源和网络带宽资源。
    3)使用内存记录数据增量操作,可以有效减少Master节点在这方面付出的I/O代价。而做成环形内存的原因,是为了保证在满⾜数据记录需求的情况下尽可能减少内存的占用量。这个环形内存的大小,可以通过repl-backlog-size参数进行设置

    Slave重连后会向Master发送之前接收到的Master replication id信息和上一次完成部分同步的offset的位置信息。如果Master能够确定这个replication id和自己的replication id(有两个)一致且能够在环形内存中找到这个offset的位置,Master就会发送从offset的位置开始向Slave发送增量数据。

    :连接正常的各个Slave节点如何接受新数据呢?
    连接正常的Slave节点将会在Master节点将数据写入环形内存后,主动接收到来自Master的数据复制信息。

    :Replication backlog的size设置多大合适呢?
    redis为Replication backlog设置的默认大小为1M,这个值可以调整。如果主服务需要执行大量的写命令,又或者主服务之间断线后重连的时间比较长,那么这个大小也许不合适。如果replication backlog的大小设置不恰当,那么PSYNC命令的复制同步模式就不能正常发
    挥作用,因此,正确估算和设置replication backlog的size非常重要。

    计算参考公式:size = reconnect_time_second * write_size_per_second*2
    

    例如如果网络中断的平均时间是60s,而主节点平均每秒产生的写命令(特定协议格式)所占的字节数为100KB,则复制积压缓冲区的平均需求为6MB,保险起见,可以设置为12MB,来保证绝大多数断线情况都可以使用部分复制。


    三、主从复制实现

    1、主从复制的开启,完全是从节点发起的,不需要在主节点上做任何事情。

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

    1)方式1–修改配置文件
    配置文件修改的是从节点的redis.conf文件,在配置文件中加入:slaveof <masterip> <masterport>

    2)方式2–使用启动命令
    启动从节点时,redis-server启动命令后加入 --slaveof <masterip> <masterport>
    在这里插入图片描述

    3)方式3–使用客户端命令
    从节点Redis服务器启动后,直接通过客户端执行命令:slaveof <masterip> <masterport>,则该Redis实例成为从节点。
    在这里插入图片描述

    2、主从复制效果展示
    1)使用info replication指令分别查看master和slave的redis信息,如下图。
    在这里插入图片描述
    2)实现主从复制后,在master端写入数据,在slave也可以读到对应的数据。
    在这里插入图片描述

    3、Slaveof命令操作内容

    • 判断当前环境是否在集群模式下,因为集群模式下不执行该命令。
    • 是否执行的是SLAVEOF NO ONE命令,该命令会断开主从的关系,设置当前节点为主节点服务器。
    • 设置从节点所属主节点的IP和port。调用了replicationSetMaster()函数。

    redis-5.0.8 Slaveof命令实现源码阅读:
    在这里插入图片描述

    void replicaofCommand(client *c) {
        /* SLAVEOF is not allowed in cluster mode as replication is automatically
         * configured using the current address of the master node. */
        if (server.cluster_enabled) { //如果是集群模式 ,则退出,不执行
            addReplyError(c,"REPLICAOF not allowed in cluster mode.");
            return;
        }
    
        /* The special host/port combination "NO" "ONE" turns the instance
         * into a master. Otherwise the new master address is set. */
        if (!strcasecmp(c->argv[1]->ptr,"no") &&
            !strcasecmp(c->argv[2]->ptr,"one")) {
            if (server.masterhost) {
                replicationUnsetMaster();  //取消原来的复制操作
                sds client = catClientInfoString(sdsempty(),c);
                serverLog(LL_NOTICE,"MASTER MODE enabled (user request from '%s')",
                    client);
                sdsfree(client);
            }
        } else {
            long port;
    
            if (c->flags & CLIENT_SLAVE)
            {
                /* If a client is already a replica they cannot run this command,
                 * because it involves flushing all replicas (including this
                 * client) */
                addReplyError(c, "Command is not valid when client is a replica.");
                return;
            }
    
            if ((getLongFromObjectOrReply(c, c->argv[2], &port, NULL) != C_OK))
                return;
    
            /* Check if we are already attached to the specified slave */
            if (server.masterhost && !strcasecmp(server.masterhost,c->argv[1]->ptr)
                && server.masterport == port) {
                serverLog(LL_NOTICE,"REPLICAOF would result into synchronization with the master we are already connected with. No operation performed.");
                addReplySds(c,sdsnew("+OK Already connected to specified master\r\n"));
                return;
            }
            /* There was no previous master or the user specified a different one,
             * we can continue. */
            replicationSetMaster(c->argv[1]->ptr, port); //设置服务器复制操作的主节点IP和端⼝
            sds client = catClientInfoString(sdsempty(),c);
            serverLog(LL_NOTICE,"REPLICAOF %s:%d enabled (user request from '%s')",
                server.masterhost, server.masterport, client);
            sdsfree(client);
        }
        addReply(c,shared.ok);
    }
    
    //replicationSetMaster函数
    /* Set replication to the specified master address and port. */
    void replicationSetMaster(char *ip, int port) {
        int was_master = server.masterhost == NULL;
    	//清除原来的主节点
        sdsfree(server.masterhost);
        
        //设置新的IP和端口
        server.masterhost = sdsnew(ip);
        server.masterport = port;
        
        //释放其他主节点
        if (server.master) {
            freeClient(server.master);	
        }
        //解除所有客户端的阻塞状态
        disconnectAllBlockedClients(); /* Clients blocked in master, now slave. */
    
        /* Force our slaves to resync with us as well. They may hopefully be able
         * to partially resync with us, but we can notify the replid change. */
        //关闭所有从节点服务器的连接,强制从节点服务器进行重新同步操作
        disconnectSlaves();
        //取消执行复制操作
        cancelReplicationHandshake();
        /* Before destroying our master state, create a cached master using
         * our own parameters, to later PSYNC with the new master. */
        if (was_master) {
            replicationDiscardCachedMaster(); //释放主节点结构的缓存,不会执行部分重同步PSYNC
            replicationCacheMasterUsingMyself();
        }
        server.repl_state = REPL_STATE_CONNECT;	//设置复制必须重新连接主节点的状态
    }
    
    

    slaveof命令是一个异步命令,执行命令的时候,从节点保存主节点的信息,确立主从关系后会立即返回,后续的复制流程在节点内部异步执行。那么如何触发复制的执行呢?
    周期性执行的函数:replicationCron()函数,该函数被服务器的时间事件的回调函数serverCron()所调用,而serverCron()函数在Redis服务器初始化时,被设置为时间事件的处理函数。
    在这里插入图片描述
    replicationCron这个函数每秒执行一次。
    在这里插入图片描述
    replicationCron()函数处理这以情况的代码如下:
    在这里插入图片描述
    replicationCron()函数根据从节点的状态,调用connectWithMaster()非阻塞连接主节点。代码如下:

    //以非阻塞的方式连接主节点
    int connectWithMaster(void) {
        int fd;
    	//连接主节点
        fd = anetTcpNonBlockBestEffortBindConnect(NULL,
            server.masterhost,server.masterport,NET_FIRST_BIND_ADDR);
        if (fd == -1) {
            serverLog(LL_WARNING,"Unable to connect to MASTER: %s",
                strerror(errno));
            return C_ERR;
        }
    	//监听主节点fd的可读和可写事件的发生,并设置其处理程序为syncWithMaster
        if (aeCreateFileEvent(server.el,fd,AE_READABLE|AE_WRITABLE,syncWithMaster,NULL) ==
                AE_ERR)
        {
            close(fd);
            serverLog(LL_WARNING,"Can't create readable event for SYNC");
            return C_ERR;
        }
    	//最近一次读到RDB文件内容的时间
        server.repl_transfer_lastio = server.unixtime;
        //从节点和主节点的同步套接字
        server.repl_transfer_s = fd;
        //处于和主节点正在连接的状态
        server.repl_state = REPL_STATE_CONNECTING;
        return C_OK;
    }
    

    4、主从复制的相关参数配置
    1)主节点相关配置

    • repl-timeout 60:与各个阶段主从节点连接超时判断有关。

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

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

    • client-output-buffer-limit slave 256MB 64MB 60:与全量复制阶段主节点的缓冲区大小有关。

    • repl-disable-tcp-nodelay no:与命令传播阶段的延迟有关。

    • masterauth <master-password>:与连接建立阶段的身份验证有关。

    • repl-ping-slave-period 10:与命令传播阶段主从节点的超时判断有关。

    • repl-backlog-size 1MB:复制积压缓冲区的大小。

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

    • min-slaves-to-write 3min-slaves-max-lag 10:规定了主节点的最小从节点数目,及对应的最大延迟。

    2)从节点相关配置

    • slaveof <masterip> <masterport>:Redis启动时起作用;作用是建立复制关系,开启了该配置的Redis服务器在启动后成为从节点。该注释默认注释掉,即Redis服务器默认都是主节点。
    • repl-timeout 60:与各个阶段主从节点连接超时判断有关。
    • slave-serve-stale-data yes:与从节点数据陈旧时是否响应客户端命令有关。
    • slave-read-only yes:从节点是否只读;默认是只读的。由于从节点开启写操作容易导致主从节点的数据不一致,因此该配置尽量不要修改。

    四、主从复制需要注意的问题

    1、持久化问题
    确保master激活了持久化,或者确保它不会在当掉后自动重启。
    因为slave是master的完整备份,因此如果master通过一个空数据集重启,slave也会被清掉。

    2、密码问题
    在配置redis复制功能的时候如果主数据库设置了密码,需要在从数据的配置文件中通过masterauth参数设置主数据库的密码,这样从数据库在连接主数据库时就会自动使用auth命令认证了。相当于做了一个免密码登录。

    3、读写分离问题
    1)延迟与不一致问题
    主从复制是异步的,延迟与数据不一致不可避免。可优化措施:
    1)优化主从之间的网络。
    2)监控主从节点延迟(通过offset判断),如果从节点延迟过大,通知应用不再通过该从节点读取数据。
    3)使用集群同时扩展写负载和读负载等。

    2)数据过期问题
    单机redis采用的删除策略:惰性删除、定期删除。
    惰性删除:服务器不主动删除数据,只有当客户端查询某个数据时,服务器判断数据是否过期来决定是否删除。
    定期删除:执行定时任务删除过期数据,对内存和CPU有影响,删除频率和执行时间有限制。

    主从复制:为了主从数据一致性,由主节点控制从节点中过期数据的删除。由于主节点的惰性删除和定期删除都不能保证及时对过期数据执行删除操作,因此当客户端通过redis从节点读取数据的时候,很容易读到已经过期的数据。

    3)故障切换
    没有使用哨兵的读写分离场景下,应用针对读和写分别连接不同的redis节点;当主节点或从节点出现问题而发生改变时,需要及时修改应用程序读写redis的连接;连接的切换可以手动进行,或者自己写监控程序进行切换。

    4、复制超时问题
    设置超时意义
    - 主节点释放从连接,释放资源。避免无效连接占用输出缓冲区、带宽、连接等。
    - 从节点超时, 重新建立连接,避免与主节点数据不一致。

    引出的问题
    1)数据同步阶段
    问题描述:如果RDB文件过大,主节点在fork子进程+保存RDB文件时耗时过多,可能会导致从节点长时间收不到数据而触发超时;此时从节点会重连主节点,然后再次全量复制,再次超时,再次重连……形成恶性循环。
    解决方案:redis单机数据量不要过大,同时适当增大repl-timeout值。

    2)命令传播阶段
    网络抖动导致个别PING命令丢失,造成的超时误判。

    3)慢查询导致的阻塞
    主节点或从节点执行一些慢查询(如key* 或 对大数据的hgetall等),导致服务器阻塞;阻塞期间无法响应复制连接中对方节点的请求,可能导致复制超时。

    5、复制中断问题
    复制中断有很多情况可以导致,主从节点超时是冲断的原因之一,最主要的原因是复制缓冲区溢出

    问题描述:
    全量复制阶段,主节点会将执行的写命令放到复制缓冲区中,该缓冲区存放的数据包括以下几个时间段内主节点执行的写命令:
    BGSAVE生成RDB文件 -> RDB文件由主节点发往从节点 -> 从节点清空老数据并载入RDB文件中的数据。
    当主节点数据量较大,或者主动节点网络延迟较大时,可能导致该缓冲区的大小超过了限制,此时主节点会断开与从节点的连接,这种情况下可能会引起全量复制 -> 复制缓冲区溢出导致连接中断->重连->全量复制->复制缓冲区溢出导致连接中断…循环不断…

    解决方法:
    复制缓冲区的大小由client-output-buffer-limit slave {hard limit} {soft limit} {soft seconds}配置,默认值为:256MB 64MB 60
    含义:如果buffer大于256MB,或者连续60s大于64MB,则主节点会断开与该从节点的连接。
    参数可以通过config set命令动态配置(不重启redis也可以生效)。

    需要注意的是,父子缓冲区是客户端输出缓冲区的一种,主节点会为每一个从节点分配复制缓冲区;而复制积压缓冲区则是一个主节点只有一个,无论它有多少个从节点。

    6、主节点重启
    主节点重启分两种情况:故障导致宕机、有计划的重启。
    1)故障导致宕机
    主节点宕机后,runid会发生变化,因此不能进行部分复制,只能进行全量复制。
    在主节点宕机的情况下,应该进行故障转移处理,将其中的一个节点升级为主节点,其他从节点从新的主节点进行复制;同时故障转移应该自动化(哨兵模式)。

    2)安全重启debug reload–有计划的重启
    主节点内存碎片率过高,或者希望调整一些只能在启动时调整的参数,这时候就需要进行安全重启了。
    如果使用普通的手段重启主节点,会使得runid发生变化,可能导致不必要的全量复制。

    为了解决这个问题,Redis提供了debug reload的重启方式:重启后,主节点的runid和offset都不受影响,避免了全量复制
    同时需要注意的是,debug reload会清空当前内存中的数据,重新从RDB文件中加载,这过程会导致直接点的阻塞,因此需谨慎使用。

    7、从节点重启
    从节点宕机重启后,其保存的主节点的runid会丢失,因此即使再次执行slaveof,也无法进行部分复制。

    8、网络中断
    1)第一种情况
    网络问题极为短暂,只造成了短暂的丢包,主从节点都没有判定超时(未触发repl-timeout);此时只需要通过REPLCONF ACK来补充丢失的数据即可。

    2)第二种情况
    网络问题时间很长,主从节点判断超时(触发了repl-timeout),且丢失的数据过多,超过了复制积压缓冲区所能存储的范围;此时主从节点无法进行部分复制,只能进行全量复制。
    为了尽可能避免这种情况的发生,应该根据实际情况适当调整复制积压缓冲区的大小;此外及时发现并修复网络中断,也可以减少全量复制。

    3)第三种情况
    介于前述两种情况之间,主从节点判断超时,且丢失的数据仍然都在复制积压缓冲区中;此时主从节点可以进行部分复制。

    展开全文
  • 复制的过程步骤如下: 1、从节点执行 slaveof 命令; 2、从节点只是保存了 slaveof 命令中主节点的信息,并没有立即发起复制; 3、从节点内部的定时任务发现有主节点的信息,开始使用 socket 连接主节点; 4、连接...

    1.复制过程

    复制的过程步骤如下:

    1、从节点执行 slaveof 命令;

    2、从节点只是保存了 slaveof 命令中主节点的信息,并没有立即发起复制;

    3、从节点内部的定时任务发现有主节点的信息,开始使用 socket 连接主节点;

    4、连接建立成功后,发送 ping 命令,希望得到 pong 命令响应,否则会进行重连;

    5、如果主节点设置了权限,那么就需要进行权限验证;如果验证失败,复制终止;

    6、权限验证通过后,进行数据同步,这是耗时最长的操作,主节点将把所有的数据全部发送给从节点;

    7、当主节点把当前的数据同步给从节点后,便完成了复制的建立流程。接下来,主节点就会持续的把写命令发送给从节点,保证主从数据一致性。

    在这里插入图片描述

    2.数据间的同步

    上面说的复制过程,其中有一个步骤是“同步数据集”,这个就是现在讲的‘数据间的同步’。

    redis 同步有 2 个命令:

    syncpsync,前者是 redis 2.8 之前的同步命令,后者是 redis 2.8 为了优化 sync 新设计的命令。我们会重点关注 2.8 的 psync 命令。

    psync 命令需要 3 个组件支持:

    1、主从节点各自复制偏移量 ;

    2、主节点复制积压缓冲区;

    3、主节点运行 ID;

    主从节点各自复制偏移量:

    1、参与复制的主从节点都会维护自身的复制偏移量。

    2、主节点在处理完写入命令后,会把命令的字节长度做累加记录,统计信息在 info replication 中的 masterreploffset 指标中。

    3、从节点每秒钟上报自身的的复制偏移量给主节点,因此主节点也会保存从节点的复制偏移量。

    4、从节点在接收到主节点发送的命令后,也会累加自身的偏移量,统计信息在 info replication 中。

    5、通过对比主从节点的复制偏移量,可以判断主从节点数据是否一致。

    主节点复制积压缓冲区:

    1、复制积压缓冲区是一个保存在主节点的一个固定长度的先进先出的队列。默认大小 1MB。

    2、这个队列在 slave 连接时创建。这时主节点响应写命令时,不但会把命令发送给从节点,也会写入复制缓冲区。

    3、他的作用就是用于部分复制和复制命令丢失的数据补救。通过 info replication 可以看到相关信息。

    主节点运行 ID:

    1、每个 redis 启动的时候,都会生成一个 40 位的运行 ID。

    2、运行 ID 的主要作用是用来识别 Redis 节点。如果使用 ip+port 的方式,那么如果主节点重启修改了 RDB/AOF 数据,从节点再基于偏移量进行复制将是不安全的。所以,当运行 id 变化后,从节点将进行全量复制。也就是说,redis 重启后,默认从节点会进行全量复制。

    如果在重启时不改变运行 ID 呢?

    1、可以通过 debug reload 命令重新加载 RDB 并保持运行 ID 不变。从而有效的避免不必要的全量复制。

    2、他的缺点则是:debug reload 命令会阻塞当前 Redis 节点主线程,因此对于大数据量的主节点或者无法容忍阻塞的节点,需要谨慎使用。一般通过故障转移机制可以解决这个问题。

    psync 命令的使用方式:

    命令格式为:   psync{runId}{offset}
    

    runId:从节点所复制主节点的运行 id
    offset:当前从节点已复制的数据偏移量

    psync 执行流程:
    在这里插入图片描述
    流程说明:从节点发送 psync 命令给主节点,runId 就是目标主节点的 ID,如果没有默认为 -1,offset 是从节点保存的复制偏移量,如果是第一次复制则为 -1.

    主节点会根据 runid 和 offset 决定返回结果:

    1、如果回复 +FULLRESYNC {runId} {offset} ,那么从节点将触发全量复制流程。

    2、如果回复 +CONTINUE,从节点将触发部分复制。

    3、如果回复 +ERR,说明主节点不支持 2.8 的 psync 命令,将使用 sync 执行全量复制。

    到这里,数据之间的同步就讲的差不多了,篇幅还是比较长的。主要是针对 psync 命令相关之间的介绍。

    3.全量复制

    全量复制是 Redis 最早支持的复制方式,也是主从第一次建立复制时必须经历的的阶段。触发全量复制的命令是 sync 和 psync。之前说过,这两个命令的分水岭版本是 2.8,redis 2.8 之前使用 sync 只能执行全量不同,2.8 之后同时支持全量同步和部分同步。

    流程如下:
    在这里插入图片描述

    介绍一下上图步骤:
    以下加粗的部分是整个全量同步耗时的地方。

    1、发送 psync 命令(spync ?-1)
    2、主节点根据命令返回 FULLRESYNC
    3、从节点记录主节点 ID 和 offset
    4、主节点 bgsave 并保存 RDB 到本地
    5、主节点发送 RBD 文件到从节点
    6、从节点收到 RDB 文件并加载到内存中
    7、主节点在从节点接受数据的期间,将新数据保存到“复制客户端缓冲区”,当从节点加载 RDB 完毕,再发送过去。(如果从节点花费时间过长,将导致缓冲区溢出,最后全量同步失败)
    8、从节点清空数据后加载 RDB 文件,如果 RDB 文件很大,这一步操作仍然耗时,如果此时客户端访问,将导致数据不一致,可以使用配置slave-server-stale-data 关闭.
    9、从节点成功加载完 RBD 后,如果开启了 AOF,会立刻做 bgrewriteaof。

    注意:

    1、如过 RDB 文件大于 6GB,并且是千兆网卡,Redis 的默认超时机制(60 秒),会导致全量复制失败。可以通过调大 repl-timeout 参数来解决此问题。

    2、Redis 虽然支持无盘复制,即直接通过网络发送给从节点,但功能不是很完善,生产环境慎用。

    4.部分复制

    当从节点正在复制主节点时,如果出现网络闪断和其他异常,从节点会让主节点补发丢失的命令数据,主节点只需要将复制缓冲区的数据发送到从节点就能够保证数据的一致性,相比较全量复制,成本小很多。

    步骤如下:
    在这里插入图片描述

    1、当从节点出现网络中断,超过了 repl-timeout 时间,主节点就会中断复制连接。

    2、主节点会将请求的数据写入到“复制积压缓冲区”,默认 1MB。

    3、当从节点恢复,重新连接上主节点,从节点会将 offset 和主节点 id 发送到主节点

    4、主节点校验后,如果偏移量的数后的数据在缓冲区中,就发送 cuntinue 响应 —— 表示可以进行部分复制

    5、主节点将缓冲区的数据发送到从节点,保证主从复制进行正常状态。

    5.心跳

    主从节点在建立复制后,他们之间维护着长连接并彼此发送心跳命令。

    心跳的关键机制如下:

    1、中从都有心跳检测机制,各自模拟成对方的客户端进行通信,通过 client list 命令查看复制相关客户端信息,主节点的连接状态为 flags = M,从节点的连接状态是 flags = S。

    2、主节点默认每隔 10 秒对从节点发送 ping 命令,可修改配置 repl-ping-slave-period 控制发送频率。

    3、从节点在主线程每隔一秒发送 replconf ack{offset} 命令,给主节点上报自身当前的复制偏移量。

    4、主节点收到 replconf 信息后,判断从节点超时时间,如果超过 repl-timeout 60 秒,则判断节点下线。

    在这里插入图片描述
    注意:为了降低主从延迟,一般把 redis 主从节点部署在相同的机房/同城机房,避免网络延迟带来的网络分区造成的心跳中断等情况。

    6.异步复制

    主节点不但负责数据读写,还负责把写命令同步给从节点,写命令的发送过程是异步完成,也就是说主节点处理完写命令后立即返回客户度,并不等待从节点复制完成。

    异步复制的步骤很简单,如下:

    1、主节点接受处理命令

    2、主节点处理完后返回响应结果

    3、对于修改命令,异步发送给从节点,从节点在主线程中执行复制的命令。

    在这里插入图片描述

    总结

    本文主要分析了 Redis 的复制原理,包括复制过程,数据之间的同步,全量复制的流程,部分复制的流程,心跳设计,异步复制流程。

    其中,可以看出,RDB 数据之间的同步非常耗时。所以,Redis 在 2.8 版本退出了类似增量复制的 psync 命令,当 Redis 主从直接发生了网络中断,不会进行全量复制,而是将数据放到缓冲区(默认 1MB)里,在通过主从之间各自维护复制 offset 来判断缓存区的数据是否溢出,如果没有溢出,只需要发送缓冲区数据即可,成本很小,反之,则要进行全量复制,因此,控制缓冲区大小非常的重要。

    展开全文
  • 【聊聊主从 – 同步原理】 从服务器会向主服务器发出SYNC指令,当主服务器接到此命令后,就会调用BGSAVE指令来创建一个子进程专门进行数据持久化工作,也就是将主服务器数据写入RDB文件中。在数据持久化期间,主...
  • 复制的过程步骤如下: 从节点执行 slaveof 命令 从节点只是保存了 slaveof 命令中主节点的信息,并没有立即发起复制 从节点内部的定时任务发现有主节点的信息,开始使用 socket 连接主节点 连接建立成功后,发送...
  • 复制的过程步骤如下: 1、从节点执行 slaveof 命令 2、从节点只是保存了 slaveof 命令中主节点的信息,并没有立即发起复制 3、从节点内部的定时任务发现有主节点的信息,开始使用 socket 连接主节点 4、连接建立...
  • 深入 Redis 主从复制的原理详解

    千次阅读 2019-03-28 17:18:37
    复制的过程步骤如下: 1、从节点执行 slaveof 命令 2、从节点只是保存了 slaveof 命令中主节点的信息,并没有立即发起复制 3、从节点内部的定时任务发现有主节点的信息,开始使用 socket 连接主节点 4、连接建立...
  • 复制过程复制的过程步骤如下:从节点执行 slaveof 命令从节点只是保存了 slaveof 命令中主节点的信息,并没有立即发起复制从节点内部的定时任务发现有主节点的信息,开始使用 socket 连接主节点连接建立成功后,发送...
  • 主从复制,是指将一台Redis服务器数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave);数据复制是单向,只能由主节点到从节点。 默认情况下,每台Redis服务器都是主节点;且一个...
  • 复制的过程步骤如下: 从节点执行 slaveof 命令 从节点只是保存了 slaveof 命令中主节点的信息,并没有立即发起复制 从节点内部的定时任务发现有主节点的信息,开始使用 socket 连接主节点 连接建立成功后,发送 ...
  • Redis 主从复制的原理2.1 全量同步2.2 增量同步2.3 Redis 主从同步策略2.4 无盘复制3. master 不能持久化时主从复制的安全问题4. 限制有 N 个以上从服务器才允许写入 1. Redis 主从复制 1.1 主从复制 和 mysql 主从...
  • (1)复制的过程步骤 从节点保存主节点的信息,redis.conf里面的slaveof配置的主节点的信息,并没有立即发起复制 从节点通过定时任务,每秒检查是否有新的master node要连接和复制,如果发现,就跟master node...
  • 本文主要针对redis主从复制的原理进行了讲解,分享出来供大家参考学习,下面话不多说了,来一起看看详细的介绍吧 1.复制过程 2.数据间的同步 3.全量复制 4.部分复制 5.心跳 6.异步复制 1.复制过程 从节点执行 ...
  • (1)初次复制:从服务器以前没有复制过任何主服务器,或者从服务器当前要复制主服务器和上一次复制的主服务器不通 (2)断线后重复制:处于命令传播阶段的主从服务器因为网络原因而中断了复制,但从服务器通过自动...
  • 3. 【Redis主从架构】Redis主从复制原理,断点续传,无磁盘化复制,key过期处理 文章目录3. 【Redis主从架构】Redis主从复制原理,断点续传,无磁盘化复制,key过期处理1. Redis主从架构数据复制原理2. 主从复制断点...
  • 为了分担读压力,Redis支持主从复制,Redis主从结构可以采用一主多从或者级联结构,Redis主从复制可以根据是否是全量分为全量同步和增量同步。 主从复制,是指将一台Redis服务器数据,复制到其他Redis服务器...
  • 1.1 LAMP+Redis主从工作的原理 LAMP+Redis工作机制:用户通过浏览器访问LAMP网站,并以用户名和密码登录到网站,默认Redis缓存中没有该用户名和密码对应列表,PHP程序会读取MYSQL数据库中的用户名和密码,然后将...
  • 常见问题 参考文章 redis的主从复制和哨兵模式
  • redis主从复制分为三个阶段 1.建立连接阶段 2.数据同步阶段 3.命令传播阶段(实时进行数据同步) ①中目的是让当前主机成为某台服务器从机,ip,port为主机ip及端口。 ①是为了找主机索要数据 数据缓存区在...
  • Redis主从复制原理

    2019-03-15 17:41:46
    Redis主从复制原理Redis主从复制原理使用场景配置复制原理参考 Redis主从复制原理 使用场景 数据冗余。作为数据热备份 故障恢复。主节点有问题,可以切换到从节点服务。 负载均衡。 读写分离。 配置 master: ...
  • 有两个或者多个redis-server,当客户端写入数据到主服务器redis-server时,主服务器数据会同步到从服务器上,主服务器负责写入数据,从服务器负责读取数据。 2、为什要使用主从复制 故障转移:单节点如果出现故障...
  • Redis主从复制的功能及实现原理

    千次阅读 多人点赞 2021-05-28 15:19:46
    Redis主从复制的功能及实现原理

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,597
精华内容 638
关键字:

redis主从复制的原理

redis 订阅