Redis 主从复制--replication 代码分析

7.1华为OD机试真题 新系统 - 奇偶三数之和 (Java/Py/C/C++/Js/Go) 7.1华为OD机试真题 新系统 - 奇偶三数之和 (Java/Py/C/C++/Js/Go) 阅读详情

源码版本:redis-3.2.3


1、redis的主从复制实现简单却功能强大,其具有以下特点:
1. 一个master支持多个slave连接,slave可以接受其他slave的连接
2. 主从同步时,master和slave都是非阻塞的

2、redis主从复制可以用来:
1. data redundancy 
2. slave作为master的扩展,提供一些read-only的服务
3. 可以将数据持久化放在slave做,从而提升master性能

3、redis 主从复制配置项(redis.conf):

slaveof <masterip> <masterport>
表示该redis服务作为slave,masterip和masterport分别为master 的ip和port
不需要特别的设置则配此选项即可、启动从时加载此配置文件

masterauth <master-password>
如果master设置了安全密码,则此处设置为相应的密码

slave-serve-stale-data yes
当slave丢失master或者同步正在进行时,如果发生对slave的服务请求:
slave-serve-stale-data设置为yes则slave依然正常提供服务
slave-serve-stale-data设置为no则slave返回client错误:"SYNC with master in progress"

repl-ping-slave-period 10
slave发送PINGS到master的时间间隔

repl-timeout 60
IO超时时间


4、代码层分析


主从复制的调度中心replicationCron函数开始:

int serverCron(struct aeEventLoop *eventLoop, long long id, void *clientData) {
/* Replication cron function -- used to reconnect to master,
     * detect transfer failures, start background RDB transfers and so forth. */
    run_with_period(1000) replicationCron();  // 每秒执行一次
}

void replicationCron(void) {  
    static long long replication_cron_loops = 0;  
  
    //slave非阻塞连接超时  
    if (server.masterhost &&  
        (server.repl_state == REPL_STATE_CONNECTING ||  
         slaveIsInHandshakeState()) &&  
         (time(NULL)-server.repl_transfer_lastio) > server.repl_timeout)  
    {  
        serverLog(LL_WARNING,"Timeout connecting to the MASTER...");  
        cancelReplicationHandshake();  
    }
    /* Bulk transfer I/O timeout? */  
    //slave receiving .rdb超时  
    if (server.masterhost && server.repl_state == REPL_STATE_TRANSFER &&  
        (time(NULL)-server.repl_transfer_lastio) > server.repl_timeout)  
    {  
        serverLog(LL_WARNING,"Timeout receiving bulk data from MASTER... If the problem persists try to set the 'repl-timeout' parameter in redis.conf to a larger value.");  
        cancelReplicationHandshake();  
    }
    /* Timed out master when we are an already connected slave? */  
    //slave连接上主服务器后出现交互超时  
    if (server.masterhost && server.repl_state == REPL_STATE_CONNECTED &&  
        (time(NULL)-server.master->lastinteraction) > server.repl_timeout)  
    {  
        serverLog(LL_WARNING,"MASTER timeout: no data nor PING received...");  
        freeClient(server.master);  
    }  
    //slave检查是否需要连接主服务器  
    if (server.repl_state == REPL_STATE_CONNECT) {  
        serverLog(LL_NOTICE,"Connecting to MASTER %s:%d",  
            server.masterhost, server.masterport);  
        //建立与主服务器的套接字连接  
        if (connectWithMaster() == C_OK) {  
            serverLog(LL_NOTICE,"MASTER <-> SLAVE sync started");  
        }
    }
    // slave发送ack给master   
    if (server.masterhost && server.master &&  
        !(server.master->flags & CLIENT_PRE_PSYNC))  
        replicationSendAck();  
  
    //master周期性发生ping给slave  
    if ((replication_cron_loops % server.repl_ping_slave_period) == 0) {  
        ping_argv[0] = createStringObject("PING",4);  
        replicationFeedSlaves(server.slaves, server.slaveseldb,  
            ping_argv, 1);  
        decrRefCount(ping_argv[0]);  
    }
    
    listRewind(server.slaves,&li);  
    while((ln = listNext(&li))) {  
        client *slave = ln->value;  
        //master发送一个空行给每个符合下面两个条件的slave,refresh slave的last-io的timer  
        //1、master需要产生一个rdb文件给slave  
        //2、等待rdb文件完成,但还没发给slave  
        if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START ||  
            (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_END &&  
             server.rdb_child_type != RDB_CHILD_TYPE_SOCKET))  
        {  
            if (write(slave->fd, "\n", 1) == -1) {  
                /* Don't worry, it's just a ping. */  
            }  
        }  
    }
    
    //master断开slave的连接  
    if (listLength(server.slaves)) {  
        listIter li;  
        listNode *ln;  
  
        listRewind(server.slaves,&li);  
        while((ln = listNext(&li))) {  
            client *slave = ln->value;  
            if (slave->replstate != SLAVE_STATE_ONLINE) continue;  
            if (slave->flags & CLIENT_PRE_PSYNC) continue;  
            if ((server.unixtime - slave->repl_ack_time) > server.repl_timeout)  
            {  
                serverLog(LL_WARNING, "Disconnecting timedout slave: %s",  
                    replicationGetSlaveName(slave));  
                freeClient(slave);  // 断开连接
            }  
        }  
    }
    
    //master没有slave,就释放掉repl_backlog的内存  
    if (listLength(server.slaves) == 0 && server.repl_backlog_time_limit &&  
        server.repl_backlog)  
    {  
        time_t idle = server.unixtime - server.repl_no_slaves_since;  
  
        if (idle > server.repl_backlog_time_limit) {  
            freeReplicationBacklog();  
            serverLog(LL_NOTICE,  
                "Replication backlog freed after %d seconds "  
                "without connected slaves.",  
                (int) server.repl_backlog_time_limit);  
        }  
    }  
    
    //master的aof功能关闭而且没有slaves,就释放scriptcache  
    if (listLength(server.slaves) == 0 &&  
        server.aof_state == AOF_OFF &&  
        listLength(server.repl_scriptcache_fifo) != 0)  
    {  
        replicationScriptCacheFlush();  
    } 
    
    //master没有在进行持久化操作  
    if (server.rdb_child_pid == -1 && server.aof_child_pid == -1) {  
        listRewind(server.slaves,&li);  


        //统计slaves中处于wait_bgsave_star的数量,最大超时时间和rdb解析能力  
        while((ln = listNext(&li))) {  
            client *slave = ln->value;  
            if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START) {  
                idle = server.unixtime - slave->lastinteraction;  
                if (idle > max_idle) max_idle = idle;  
                slaves_waiting++;  
                mincapa = (mincapa == -1) ? slave->slave_capa :  
                                            (mincapa & slave->slave_capa);  
            }  
        }  
          
        if (slaves_waiting && max_idle > server.repl_diskless_sync_delay) {  
            //有超时的处于SLAVE_STATE_WAIT_BGSAVE_START的slave  
            startBgsaveForReplication(mincapa);  
        }  
    }
  
    //刷新延迟小于阈值的slave的数量  
    refreshGoodSlavesCount();  
    replication_cron_loops++; /* Incremented with frequency 1 HZ. */  
}




下面分开从slave流程分析:
slave需要连接master,调用 void replicationSetMaster(char *ip, int port) 设定ip:port
通过 connectWithMaster() 连接master

连接成功后则启动注册事件:

void syncWithMaster(aeEventLoop *el, int fd, void *privdata, int mask) 

syncWithMaster是slave连接上master后的主从复制的同步实现

主从复制的详细的步骤如下:
1、设置主服务器的地址和端口
2、建立套接字连接
3、发送ping命令
4、身份验证
5、发送端口信息
6、同步
7、命令传播




void syncWithMaster(aeEventLoop *el, int fd, void *privdata, int mask) {      
...
    /* Check for errors in the socket. */  
    if (getsockopt(fd, SOL_SOCKET, SO_ERROR, &sockerr, &errlen) == -1)  
        sockerr = errno;  
    if (sockerr) {  
        serverLog(LL_WARNING,"Error condition on socket for SYNC: %s",  
            strerror(sockerr));  
        goto error;  
    }
  
    //发送ping给master  
    if (server.repl_state == REPL_STATE_CONNECTING) {  
        serverLog(LL_NOTICE,"Non blocking connect for SYNC fired the event.");  
        aeDeleteFileEvent(server.el,fd,AE_WRITABLE);  
        server.repl_state = REPL_STATE_RECEIVE_PONG;  
        err = sendSynchronousCommand(SYNC_CMD_WRITE,fd,"PING",NULL);  
        if (err) goto write_error;  
        return;  
    }  
  
    if (server.repl_state == REPL_STATE_RECEIVE_PONG) {  
        //接收ping的回复  
        err = sendSynchronousCommand(SYNC_CMD_READ,fd,NULL);  
        if (err[0] != '+' &&  
            strncmp(err,"-NOAUTH",7) != 0 &&  
            strncmp(err,"-ERR operation not permitted",28) != 0)  
        {  
            serverLog(LL_WARNING,"Error reply to PING from master: '%s'",err);  
            sdsfree(err);  
            goto error;  
        } else {  
            serverLog(LL_NOTICE,  
                "Master replied to PING, replication can continue...");  
        }  
        sdsfree(err);  
        server.repl_state = REPL_STATE_SEND_AUTH;  
    }  
  
    //身份验证  
    if (server.repl_state == REPL_STATE_SEND_AUTH) {  
        err = sendSynchronousCommand(SYNC_CMD_WRITE,fd,"AUTH",server.masterauth,NULL);  
        server.repl_state = REPL_STATE_SEND_PORT;  
    }  
    if (server.repl_state == REPL_STATE_RECEIVE_AUTH) {  
        //接收验证的回复  
        err = sendSynchronousCommand(SYNC_CMD_READ,fd,NULL);  
        server.repl_state = REPL_STATE_SEND_PORT;  
    }  
  
    //发送listening-port给master   
    if (server.repl_state == REPL_STATE_SEND_PORT) {  
        sds port = sdsfromlonglong(server.port);  
        err = sendSynchronousCommand(SYNC_CMD_WRITE,fd,"REPLCONF",  
                "listening-port",port, NULL);  
        server.repl_state = REPL_STATE_RECEIVE_PORT;  
    }  
     
    //接收"replconf listening-port"的回复     
    if (server.repl_state == REPL_STATE_RECEIVE_PORT) { 
        err = sendSynchronousCommand(SYNC_CMD_READ,fd,NULL);  
        server.repl_state = REPL_STATE_SEND_CAPA;  
    }  
    //告知master自己可以解析rdb的格式  
    if (server.repl_state == REPL_STATE_SEND_CAPA) {    
        err = sendSynchronousCommand(SYNC_CMD_WRITE,fd,"REPLCONF",  
                "capa","eof",NULL);  
        server.repl_state = REPL_STATE_RECEIVE_CAPA;  
    }  
    //接收"replconf capa eof"的回复    
    if (server.repl_state == REPL_STATE_RECEIVE_CAPA) {  
        err = sendSynchronousCommand(SYNC_CMD_READ,fd,NULL);  
        server.repl_state = REPL_STATE_SEND_PSYNC;  
    }  
  
    //slave发送psync给master,如果有cached_matster,进行部分重同步;反之进行完整重同步  
    if (server.repl_state == REPL_STATE_SEND_PSYNC) {  
        if (slaveTryPartialResynchronization(fd,0) == PSYNC_WRITE_ERROR) {  
            err = sdsnew("Write error sending the PSYNC command.");  
            goto write_error;  
        }  
        server.repl_state = REPL_STATE_RECEIVE_PSYNC;  
        return;  
    }  
  
    //接收master psync的回复,进行同步  
    psync_result = slaveTryPartialResynchronization(fd,1);  
    if (psync_result == PSYNC_WAIT_REPLY) return; /* Try again later... */  
  
    if (psync_result == PSYNC_CONTINUE) {  
        serverLog(LL_NOTICE, "MASTER <-> SLAVE sync: Master accepted a Partial Resynchronization.");  
        return;  
    }  
    disconnectSlaves(); /* Force our slaves to resync with us as well. */  
    freeReplicationBacklog(); /* Don't allow our chained slaves to PSYNC. */  


    //如果master不支持psync,就改用sync进行同步(老版本的同步机制)  
    if (psync_result == PSYNC_NOT_SUPPORTED) {  
        serverLog(LL_NOTICE,"Retrying with SYNC...");  
        if (syncWrite(fd,"SYNC\r\n",6,server.repl_syncio_timeout*1000) == -1) {  
            serverLog(LL_WARNING,"I/O error writing to MASTER: %s",  
                strerror(errno));  
            goto error;  
        }  
    }  
  
    /* Setup the non blocking download of the bulk file. */  
    // 负责从连接中读取主服务器建立的同步文件,可分多次读完所有同步数据。
    // 在数据超过8MB后,每次读取操作都会进行写磁盘操作,如果在最后才进行
    // 写磁盘操作可能会造成极大的延迟。
    if (aeCreateFileEvent(server.el,fd, AE_READABLE,readSyncBulkPayload,NULL)  
            == AE_ERR)  
    {  
        serverLog(LL_WARNING,  
            "Can't create readable event for SYNC: %s (fd=%d)",  
            strerror(errno),fd);  
        goto error;  
    }  
...
}

void readSyncBulkPayload(aeEventLoop *el, int fd, void *privdata, int mask) {
//读取master发过来的RDB大小以及文件内容保存到本地文件中;
//如果读取完毕,那么调用rdbLoad加载文件内容。并考虑重新启动startAppendOnly
//看看是否文件全部接收完毕,如果完毕
    if (server.repl_transfer_read == server.repl_transfer_size) {
    serverLog(LL_NOTICE, "MASTER <-> SLAVE sync: Flushing old data");
    
    // 清空整个数据库,这个操作非常重,如果当前正在做BGSAVE,
    // 那么会导致快照的COW写时复制机制失效,严重耗费物理内存。
    emptyDb(replicationEmptyDbCallback);
    
    //开始加载RDB文件到内存数据结构中,这个要花费不少时间的。
    if (rdbLoad(server.rdb_filename) != REDIS_OK) {
    ...
    }
    }


}

这里有点很重要的事情需要记录说明一下:


slave从master读取回来最新的RDB文件后,准备加载数据库的步骤为:
1、将读取回来的临时文件rename放到server.rdb_filename文件名里面;
2、再清空整个数据库;
3、调用rdbLoad(server.rdb_filename)将server.rdb_filename 文件加载到内存;
4、开始接收master的最新数据;

有2个很重的操作:emptyDb() 和 rdbLoad(server.rdb_filename),前者会清空整个数据库,这样势必导致会
扫遍所有申请的物理内存并释放;后者加载整个RDB文件就不用说了,重新申请内存,并且一定会申请那么多
物理内存的,因为会访问。

本来巧妙的BGSAVE快照能利用COW、但此时却被emptyDb 和rdbLoad 给失效了,从而导致本来只占用55%物理内存的redis这下需要110%的物理内存,于是没办法只能swap,引起系统进入颠簸状态。


首先允许BGSAVE 和 SYNC同时进行,本身就会导致内存可能翻倍的问题。
再者可能会导致--从库备份和同步时小概率存在较严重数据错乱。


解决方案就是: 不允许BGSAVE和slave-SYNC同时进行。

以上就是slave的主要流程处理函数。

=====================


master端:

master对于slave的连接和client的连接统一处理,在接收到slave发出的SYNC命令后,执行syncCommand,syncCommand 将查看当前状态,如果正在做快照,则等待,否则启动后台进程做快照。


void syncCommand(redisClient *c) { 

/* SYNC can't be issued when the server has pending data to send to 
     * the client about already issued commands. We need a fresh reply 
     * buffer registering the differences between the BGSAVE and the current 
     * dataset, so that we can copy to other slaves if needed. */  
    if (listLength(c->reply) != 0) {  
        addReplyError(c,"SYNC is invalid with pending input");  
        return;  
    }
    
  redisLog(REDIS_NOTICE,"Slave ask for synchronization");  
    /* Here we need to check if there is a background saving operation 
     * in progress, or if it is required to start one */  
    if (server.bgsavechildpid != -1) {  
       .....  
    } else {  
        /* Ok we don't have a BGSAVE in progress, let's start one */  
        redisLog(REDIS_NOTICE,"Starting BGSAVE for SYNC");  
        if (rdbSaveBackground(server.dbfilename) != REDIS_OK) {  
            redisLog(REDIS_NOTICE,"Replication failed, can't BGSAVE");  
            addReplyError(c,"Unable to perform background save");  
            return;  
        }  
        c->replstate = REDIS_REPL_WAIT_BGSAVE_END;  
    }
    
}


在完成快照后,执行updateSlavesWaitingBgsave函数,updateSlavesWaitingBgsave将查看当前master的各个slave的状态,如果发现有在等待bgsave完成的,则注册事件sendBulkToSlave,sendBulkToSlave将快照文件发送给slave。

void updateSlavesWaitingBgsave(int bgsaveerr) {  
aeDeleteFileEvent(server.el,slave->fd,AE_WRITABLE); //删除之前的写回调
//注册新的写回调
aeCreateFileEvent(server.el, slave->fd, AE_WRITABLE, sendBulkToSlave, slave); 
}

为了避免阻塞应用,每次只传输16K数据
void sendBulkToSlave(aeEventLoop *el, int fd, void *privdata, int mask) {  
    ......  
    lseek(slave->repldbfd,slave->repldboff,SEEK_SET); //指针移动到上次发送的位置  
    buflen = read(slave->repldbfd,buf,REDIS_IOBUF_LEN); //读取16K数据  
    ......  
    if ((nwritten = write(fd,buf,buflen)) == -1) { //传输数据到slave  
        if (errno != EAGAIN) {  
            redisLog(REDIS_WARNING,"Write error sending DB to slave: %s",  
                strerror(errno));  
            freeClient(slave);  
        }  
        return;  
    }  
    slave->repldboff += nwritten; //更新已发送位置  
    ......  
}


总结一下:
从服务器对主服务器的同步操作需要通过向主服务器发送SYNC命令来完成,以下是SYNC命令的执行步骤:
1、从服务器向主服务器发送SYNC命令;
2、收到SYNC命令的主服务器执行BGSAVE命令,在后台生成一个RDB文件,并使用一个缓冲区记录从现在开始执行的所有写命令;
3、当主服务器的BGSAVE命令执行完毕时,主服务器会将BGSAVE命令生成的RDB文件发送给从服务器,
   从服务器接收并载入这个RDB文件,将自己的数据库状态更新至主服务器执行BGSAVE命令时的数据库状态。
4、主服务器将记录在缓冲区里面的所有写命令发送给从服务器,从服务器执行这些写命令,将自己的数据库状态更新至主服务器数据库当前所处的状态。


SYNC命令是非常消耗资源的,因为每次执行SYNC命令,主从服务器需要执行一下操作:

1、主服务器需要执行BGSAVE命令来生成RDB文件,这个生成操作会耗费主服务器大量的CPU、内存和磁盘I/O资源;
2、主服务器需要将自己生成的RDB文件发送给从服务器,这个发送操作会耗费主从服务器大量的网络资源(带宽和流量),并对主服务器响应命令请求的时间产生影响;
3、接收到RDB文件的从服务器需要载入主服务器发来的RDB文件,并且在载入期间,从服务器会因为阻塞而没办法处理命令请求。


比我分析的更好的:

http://www.cnblogs.com/lukexwang/p/4711977.html


基于MATLAB的井筒多相流模拟 井筒多相流的模拟可以基于不同的数学模型和计算方法。其中,最常用的模型之一是多相流模型,它基于质量守恒、动量守恒和能量守恒等原理,描述了流体在井筒中的流动行为。对于井筒多相流的模拟和分析可以帮助我们理解和优化油气田开发过程中的流体行为,从而提高产量和效率。在本文中,我们将介绍如何使用MATLAB进行井筒多相流的模拟,并提供相应的源代码。需要注意的是,以上示例是一个简化的模拟,仅用于演示如何使用MATLAB进行井筒多相流模拟。实际应用中,我们需要考虑更多的物理过程和参数,并使用更复杂的数值方法和模型进行模拟。 阅读详情

相关推荐

基于Dify构建银行智能客服:从意图识别到多RAG架构的实战解析

本文深入解析了如何利用Dify平台构建银行智能客服系统。从传统客服痛点出发,详细阐述了基于意图识别精准分类用户需求,并通过多RAG架构解决知识混淆问题,实现高效、准确的业务响应。文章重点介绍了结合工具调用实现业务流程自动化,并强调了数据本地化部署、内容安全过滤等银行级安全合规实践,为金融行业AI应用提供了实战指南。

yog99的博客 926

redis节点迁移(主从同步过程及深度理解RDB持久化)

开始前先说明一下环境 redis规模是在kubernetes环境下搭建的集群三主三从模式 使用hostpath将数据保存在宿主机上 6个POD分布在三台机器上 需求是要把6个POD分开调度到6台机器上 迁移的大概想法就是 redis的三个master节点不做迁移 只迁移三个slave 因为是生产环境中 安全第一 迁移前保证集群状态正常以及确认master节点分布在已有的主机节点上 确认新迁移的主机节点数据目录存在 备份数据 三个master节点就可以 这里就不贴三个图片了 通过控制器调整sl

weixin_47329659的博客 1104

告别夜间噪点!用瑞芯微RV1126B的AI-ISP,手把手教你打造0.01Lux超低光摄像头

本文详细介绍了如何利用瑞芯微RV1126B芯片的AI-ISP技术,打造0.01Lux超低光摄像头,解决夜间噪点问题。通过AI算法与图像信号处理的深度融合,RV1126B的3TOPS边缘算力实现了像素级AI降噪和语义感知增强,显著提升低光环境下的图像质量。文章包含硬件选型、软件配置和实战调优指南,助力开发者在AIoT领域实现高性能视觉应用。

weixin_33725722的博客 565

Redis高可用(三)- 主从复制

主从复制:将数据从一台机复制到另一台机。前者为主节点(master),后者为从节点(slave);数据的复制是单向的,只能从主节点到从节点。默认情况下,每台Redis服务器都是主节点,一个主节点可以有多台从节点,一个从节点只能有一个主节点。复制是单向的,复制就会带来数据一致性问题,无可避免,尽量缩短。主从复制需要在从节点发起,不需要在主节点做任何事情,有三种方式: 通过slaveof no one断开,从节点断开链接,不会删除已有的数据,只是不再接受主节点新的数据变化。清除保存的主库的runid,当下一次执

weixin_40074110的博客 1036

配置思科交换机冗余链路汇聚

本文对交换机端口汇聚配置进行说明

istrangeboy&begin zero的博客 6684

YOLOv11+SAHI实战:5步搞定无人机航拍小目标检测(附VisDrone数据集调参技巧)

本文详细介绍了如何结合YOLOv11目标检测框架与SAHI切片推理技术,高效解决无人机航拍图像中的小目标检测难题。通过VisDrone数据集调参技巧和5步实战指南,帮助开发者快速构建高性能检测系统,显著提升小目标检测的准确率和效率。

rum55的博客 190

Redis(九):Redis的主从同步

1、全同步 2、命令传播 2.1 旧版复制功能的缺陷 2.2 新版复制功能的实现 redis的复制功能分为同步和命令传播两个操作,同步操作用于将从服务器的数据库状态更新至主服务器所处的数据库状态。命令传播操作则用于主服务器的数据库状态被修改时,导致主从服务器的数据库状态出现不一致时,让主从服务器的数据库重新回到一致状态。redis的复制功能主要通过执行SLAVEEOF命令来实现。 1、全同步 从服务器对主服务器的同步操作需要通过向主服务器发送SYNC命令来完成,以下是SY...

蓬莱道人的博客 1503

AAAI 2025杰出论文解读:神经符号推理与生物多样性计算的突破性进展

本文深度解读了AAAI 2025两篇杰出论文的突破性进展。南京大学周志华团队提出“溯因反射”框架,高效解决神经符号推理中的“不一致性”核心难题,为构建可靠、可解释的AI系统提供了新路径。斯坦福大学等机构的DiVShift研究,则系统分析了公民科学数据中的复杂分布偏移,为利用海量数据精准监测生物多样性及应对AI数据偏差提供了关键方法论。

weixin_29085865的博客 501

Redis主从同步原理

master执行bgsave后就去处理别的请求了,bgsave执行成功后会在serverCron中触发backgroundSaveDoneHandler,进而调用updateSlavesWaitingBgsave,它做的事情就是依次向所有复制状态为SLAVE_STATE_WAIT_BGSAVE_END的slave传输rdb文件。如果有级联的slave,需要断开连接,让他们重连;在准备阶段,slave发送psync指令后,就等待master的回复,当收到全量同步的回复后,开始执行全量同步流程。

liys0811的博客 281

dolphinscheduler集群服务一键安装启动实现流程剖析

通过以上分析我们基本梳理清楚了整个dolphinscheduler项目的一键安装启动逻辑, 我们现在在通过一张图正好理一下整个实现流程。关于一键停止集群服务及一件查询集群各个角色服务实例运行状态的实现也都在stop-all.sh/status-all.sh及dolphinscheduler-daemon.sh这三个脚本中, 有兴趣自行研究。写这篇文章的核心目的不仅在于给大家分享如何优秀的开源项目的一键安装部署的实现过程。

最爱嫣夜来 1207

AutoSAR_BSW高阶 7. Signal Group 信号组

Autosar BSW的高级配置是实现复杂汽车电子系统的关键步骤之一。通过合理配置信号组和使用适当的参数,您可以提高系统性能,确保数据的可靠传输。在本博客中,我们深入探讨了信号组的概念和高级配置参数,并提供了示例代码,希望这些信息能够帮助您更好地理解和应用Autosar BSW的高级配置。如果您在配置过程中遇到任何问题,不妨寻求专业支持,以确保您的汽车电子系统能够顺利运行。Autosar COM 模块是一个广泛应用于汽车行业的关键技术,它使不同的电子控制单元能够有效地通信和协作。

一直在水些技术小文 663

redis REPLCONF 命令详解

REPLCONF是 Redis 主从复制(Replication)中用于配置复制流程的内部命令。它主要用于主节点和从节点之间的通信,帮助实现复制状态同步、心跳检测和偏移量确认等功能。以下是REPLCONF。

zfj321的博客 1050

用一台笔记本跑起 SAP HANA:从 express edition 的定位,到本地硬件门槛与安装实操

SAP HANA是面向个人开发者、初创团队与教学科研场景的精简发行版,保留了in-memory列存引擎、SQLScriptAFLGraphSpatial等核心能力,可免费用于开发与一定规模的生产用途(上限为 32 GB RAM)。它最大的特征,是能在资源受限的laptop或上快速落地,让你在本地完成从建模、开发到测试的完整闭环。SAP在交付形态上,提供了多种安装包:预配置的VM OVA、面向Linux的二进制安装包,以及历史上出现过的容器化方案;你可以按现有设备与熟悉的运维方式择优选择。官方文档把VM。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 537

浅谈redis主从复制的replication buffer 和 replication backlog

浅谈redis配置文件的replication buffer 和 replication backlog配置参数

a1076067274的博客 7017

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Redis工作笔记-主从复制Replication

目录 概述 操作 概述 在Redis中配置Master-Slave模式非常简单,Redis中主从复制的特点和优势: 1. 同一个Master可以同步多个Slaves。 2. Slave同样可以接受其他Slaves的连接和同步请求,可以有效的分载Master的同步压力,所以可以将Redis的Replication架构视为图结...

IT1995的博客 4631

深入 Redis 主从复制与数据同步机制

在 Redis 的主从复制(replication)中,数据的可靠性和一致性是至关重要的,特别是在面对网络中断、主节点故障或复制延迟时。本文将深入探讨 Redis 主从复制中的几个关键概念,包括 Replication ID、Replication Offset、Replication Buffer 以及部分重同步(PSYNC),并结合具体的使用场景和指令提供全面的知识和实践建议。

m0_61338779的博客 1808

Redis 主从复制

Redis主从复制采用分布式架构(一主多从或树形结构),实现读写分离和数据冗余。核心流程包括全量同步(首次/异常时通过RDB快照恢复)和增量同步(断线重连时通过复制积压缓冲区恢复)。主节点异步同步数据到从节点,保证高性能但可能存在短暂延迟。从节点默认只读,确保数据一致性。Redis 2.8+引入的psync命令通过Replication ID和Offset机制,解决了旧版sync全量同步的性能问题。主从复制有效提升了Redis的并发处理能力和容灾能力。

weixin_45251121的博客 1285

Redis 主从复制Replication功能

特别注意:我用的redis版本是5,老版本没有下文中的某些命令。 如果你们用的redis版本是2、3、4,请略过该文。 请在我的开源博文:Centos7 安装升级Redis 5https://my.oschina.net/u/154866/blog/4306415的基础上看下文,我是接着续写 把redis默认配置文件redis.conf重命名为redisMaster.conf(名字可以随便起,但最好一看名字就知道意思) mv redis.conf redisMaster.conf ..

董广明的博客 393

Redis主从复制(replication)

redis主从复制

weixin_44793245的博客 922

Redis replication_buffer 与 replication_backlog_buffer 区别与联系 | 复制缓冲区、复制积压缓冲区

本文简略阐明replication_buffer、replication_backlog_buffer之间的关系,附带redis 版本5.0+ 6.2.6的下载和安装。 前者是复制缓冲区,主要用于首次rdb后的首次增量同步数据。后者复制积压缓冲区主要用于常规的增量数据同步

血煞长虹 的专栏 4554

【Redis】主从复制 - 源码

因为主从复制的过程很复杂, 同时核心逻辑主要集中在这个文件中, 避免篇幅过大, 所以将主从复制中涉及这个文件的代码集中到了另一篇文章。在当前文章主要分析主从复制的大体代码逻辑, 如果需要了解整体的过程, 可以配合这篇文章。

LCN29的博客 1417

[特殊字符] Redis 主从复制机制(Replication)

Redis 主从复制(Replication)是一种数据冗余机制,它允许一个 Redis 主服务器(Master)将数据同步到一个或多个从服务器(Slave),形成一主多从的集群架构。通过主从复制,可以实现:✅ 数据冗余,避免单点故障(如主服务器宕机、硬盘损坏);✅ 读写分离,提高系统读性能;✅ 为后续的高可用(哨兵 Sentinel)和分布式架构(Cluster)打基础。

2301_80320652的博客 964

redis主从复制

redis主从复制,是指将一台Redis服务器的数据,复制到其他的Redis服务器。前者称为主节点(master),后者称为从节点(slave)。数据的复制是单向的,只能由主节点到从节点。 Redis Replication是一种 master-slave 模式的复制机制,这种机制使得 slave 节点可以成为与 master 节点完全相同的副本,可以采用一主多从或者级联结构。

misakivv的博客 1241

Redis主从复制

Redis主从复制前言 通过持久化功能,Redis保证了即使在服务器重启的情况下也不会丢失(或少量丢失)数据,但是由于数据是存储在一台服务器上的,如果这台服务器出现故障,比如硬盘坏了,也会导致数据丢失。 为了避免单点故障,我们需要将数据复制多份部署在多台不同的服务器上,即使有一台服务器出现故障其他服务器依然可以继续提供服务。 这就要求当一台服务器上的数据更新后,自动将更新的数据同步到其他服务...

Coding Farmer的博客 1万+

Redis 主从复制实现的原理

Redis 主从复制是指把 Redis 主节点的数据同步到从节点的过程,使得主节点的数据和从节点的数据保持一致。

Mylqs的博客 1423

10、认识redis的主从复制

Redis 中的主从复制协议有多次升级,所以这里我们从 2.8 版本开始一步步介绍 Redis 主从复制协议的升级和优化过程。在 Redis 2.8 版本之前,主从复制的核心流程如下:这里简单描述一下上图的流程。首先,在从库启动之后,会根据配置主动请求主库,建立网络连接。连接完成之后,从库会向主库发送 SYNC 命令,发起数据同步的请求。

joeyhhhhh的博客 1465

REDIS之主从复制(REPLICATION)

主从同步可以用于实现读写分离,减轻服务器读写压力,也可以用来做容灾备份,REDIS实现了这一功能,下面跟大家分享一下,我的学习笔记。 目录 1 概念介绍 2 旧版复制功能的实现 2.1 同步 2.2 命令传播 2.3 旧版复制功能的缺陷 3 新版复制功能实现 3.1 部分重同步的实现 3.1.1 复制偏移量 3.1.2 复制积压缓冲区 3.1.3 服务器运行ID 3.2 PSYNC命令的实现 1 概念介绍 用户可以通过slaveof命令或者配置slaveof选项,让...

不完美的红烧肉的博客 2434

Redis 主从复制(replication)

Redis 主从模式(Master-Slave)是使用较多的一种架构。主(Master)和从(Slave)分别部署在不同的服务器上,当主节点服务器写入数据时,同时也会将数据同步至从节点服务器,通常情况下,主节点负责写入数据,而从节点负责读取数据

KingCruel的专栏 719
上一篇: Redis 之BIO与RIO
下一篇: Android4.4深入浅出之SurfaceFlinger总体结构
andyhuabing
博客等级 码龄19年 704粉丝 165原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值