分析:Redis主从复制_第1页
分析:Redis主从复制_第2页
分析:Redis主从复制_第3页
已阅读5页,还剩2页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

分析:Redis主从复制

那么Redis2.4.16的全量复制与Redis2.8的部分复制是如何实现的呢?如下图所示,这5个状态是Slave在主从复制过程涉及到的几个状态,其中REDIS_REPL_NONE是Redis启动时候默认的状态。图1-2所示的四个状态表示站在Master的角度来看,Slave所处于的状态,因为Slave在Master端看来就是一个特殊的client(同理Master在Slave端看来也是一个特殊的client)。/*Slavereplicationstate–Slaveside*/#defineREDIS_REPL_NONE0/*Noactivereplication*/#defineREDIS_REPL_CONNECT1/*MustconnecttoMaster*/#defineREDIS_REPL_CONNECTING2/*ConnectingtoMaster*/#defineREDIS_REPL_TRANSFER3/*Receiving.rdbfromMaster*/#defineREDIS_REPL_CONNECTED4/*ConnectedtoMaster*/Slave自身的状态#defineREDIS_REPL_WAIT_BGSAVE_START3/*Masterwaitsbgsavetostartfeedingit*/#defineREDIS_REPL_WAIT_BGSAVE_END4/*MasterwaitsbgsavetostartbulkDBtransmission*/#defineREDIS_REPL_SEND_BULK5/*MasterissendingthebulkDB*/#defineREDIS_REPL_ONLINE6/*bulkDBalreadytransmitted,receiveupdates*/Master端的Slave状态Redis在接收到“slaveofipport”命令以后,首先会将自身的状态置为REDIS_REPL_CONNECT,表示需要与自己的Master连接,此时Slave并没有与Master做连接。Redis每隔100ms会调用serverCron()函数一次,每10次serverCron()的调用会调用replicationCron()一次,即每1s会调用一次replication()函数。在replication()函数中,会检查Slave的状态,如果是处于REDIS_REPL_CONNECT状态,就会建立syncWithMaster()的事件处理函数,并将Slave的状态改成REDIS_REPL_CONNECTING。syncWithMaster()函数主要是向Master发送sync命令,当该事件处理函数被触发以后会将Slave的状态改成REDIS_REPL_TRANSFER,表示Slave已经准备就绪要接收Master生成的rdb文件。回到Master的角色,Master发现有一个Slave连接上来,如果此时的Master一个Slave都没有且没有后台快照进程,则启动一个后台进程将当前内存中的数据生成一个rdb文件,同时将Slave的状态置为REDIS_REPL_WAIT_BGSAVE_END状态,表示该Slave等待Master的快照进程结束。在后台进行生成rdb文件的时候,如果有对redis的更新命令,Master会将这些更新命令存到该Slave的buffer中,如果buffer满了会另外开辟list来存储这些更新命令。当后台快照进程结束,Master会将该Slave的状态改为REDIS_REPL_SEND_BULK,同时注册sendBulkToSlave()事件处理函数用于将生成的rdb文件传输给Slave。等rdb传输结束以后,sendBulkToSlave()事件函数会被删除,Slave的状态会被更改为REDIS_REPL_ONLINE,另外再注册sendReplyToClient()事件函数,将Master在快照内过程中的所有更新操作(Slave的buffer里存的命令)发给Slave。再回到Slave的角色,当Master向Slave传输完rdb文件以后,Slave自身会将状态改为REDIS_REPL_CONNECTED,表示复制已完成,处于与Master保持实时同步的状态。上述描述的状态转换如图1-3所示,由图中可知,站在Slave角色看,当出现网络中断的时候不管Slave本身是处于REDIS_REPL_CONNECTING、REDIS_REPL_REPL_TRANSFER还是REDIS_REPL_CONNECTED,都会调用相应的处理函数使Slave进入REDIS_REPL_CONNECT状态,这就意味着Slave需要重新向Master发送sync命令,重新进行一次全量同步过程。图中的REDIS_REPL_WAIT_BGSAVE_START状态是在Slave连接上Master的时候(站在Master的角色看),当时Master刚好后台有快照进程且该快照进程生成的rdb不适合直接传给该Slave时出现的状态,则将Slave的状态置为REDIS_REPL_WAIT_BGSAVE_START。如果此时有快照进程且找到了另外的发起快照进程的Slave,只需要将另外的Slave的buffer内容拷贝到该Slave的buffer中,然后直接进入REDIS_REPL_WAIT_BGSAVE_END状态。如果此时没有后台快照进程,Slave直接进入REDIS_REPL_WAIT_BGSAVE_END状态,同时启动一个后台快照进程。在上述状态转图中存在的最大问题在于任何网络闪断都会导致Slave与Master重连,然后重新进入快照过程,需要花费较长的时间重新传输rdb文件,而Slave在接收完rdb文件以后试图将rdb文件恢复到内存的过程中是不能服务的(除info命令外)。所以提供部分复制至少可以做到在网络闪断且更新命令不太多的情景下能够尽量的避免全量复制的方案就显得尤为重要。庆幸的是Redis2.8中里已经能够做到在网络闪断的情况下,Slave重新连接上Master以后,仅仅只传输闪断期间的更新命令。在Redis2.8中redisServer结构中增加了一个成员:charrunid[REDIS_RUN_ID_SIZE+1];/*IDalwaysdifferentateveryexec.*/该runid是由一个getRandomHexChars()函数生成的每次不同的一个唯一标识,不同Redis实例之间该runid是不同的,同一个Redis重启以后,其runid和之前的runid也是不同的。还增加了比较重要的几项数据成员char*repl_backlog;/*Replicationbacklogforpartialsyncs*/longlongrepl_backlog_size;/*Backlogcircularbuffersize*/longlongrepl_backlog_histlen;/*Backlogactualdatalength*/longlongrepl_backlog_idx;/*Backlogcircularbuffercurrentoffset*/longlongrepl_backlog_off;/*Replicationoffsetoffirstbyteinthebacklogbuffer.*/time_trepl_backlog_time_limit;/*TimewithoutSlavesafterthebackloggetsreleased.*/time_trepl_no_Slaves_since;/*WehavenoSlavessincethattime.Onlyvalidifserver.Slaveslenis0.*/repl_backlog是redis用于存储更新命令的一块buffer,在部分复制的时候Slave会请求Master从这块buffer中获取闪断情况下丢失的更新操作。repl_backlog在redis启动的时候初始化为NULL,当有Slave连接上来的时候,会被指向创建的buffer,默认为1024*1024(即1Mb)。repl_backlog_size表示该buffer的大小(默认1024*1024,即1Mb)。该buffer是作为一个环形缓存区使用的,当有数据超过buffer的大小以后就会重新从buffer的头部开始写入。repl_backlog_idx表示当前缓存数据的尾部(因为是环形buffer)。repl_backlog_off是全局缓存的偏移量,从开始缓存数据起一直在增长。如果Master一个Slave都没有,则超过一段时间以后repl_backlog会被释放,默认超时时间是1小时。Redis2.8的主从复制如图1-5所示,Slave如果与Master的连接超时了,Slave会将调用freeClient(server.Master)把连接关闭。该freeClient()函数与2.4版本的相比做了改动,会将Master对应的数据结构的一些信息存起来作为cacheMaster,其中后续被用于部分复制的最重要的两个信息一个是Masterrunid,另一个是reploff。reploff是Slave端接收到Master端传递过来的命令以后不断更新记录的全局偏移量的值,该值和Master端的repl_backlog_off对应,正常情况下reploff<=repl_backlog_off。如果Slave尝试部分复制失败以后,就会将该cacheMaster释放。Redis2.8中主从复制的过程增加了REDIS_RECIVE_PONG状态,该状态作为试图与Master同步的时候先ping一下的一个中间状态。当ping通以后,Slave首先会尝试部分复制,从cacheMaster中拿出Masterrunid和reploff传给Master,表示请求部分复制。第一次的时候,由于Slave端的cacheMaster是NULL,所以Slave向Master发送的runid是“?”,偏移量是“-1”,当Master收到这两个变量以后会将自身的runid和实际偏移量发送给Slave,同时让Slave发起一次全量同步。Slave与Master完全同步以后,maste的更新命令会被存到repl_backlog中,同时不断更新偏移量等相关变量。这些更

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论