《Redis复制机制技术详解.docx》由会员分享,可在线阅读,更多相关《Redis复制机制技术详解.docx(10页珍藏版)》请在第一文库网上搜索。
1、Redis复制机制技术详解Redis复制技术是实现Redis哨兵、集群高可用部署和Redis高扩展性的基石。RediS从实例通过复制主实例使得主从之间数据达到最终一致性,复制过程包括复制初始化、数据同步和命令传播三个阶段。复制初始化RediS实例收到rep1icaofMASTER_IPMASTEi1PORT命令(老版本中使用S1aVeOf命令)后与主实例进行连接并与主实例同步数据。执行rep1icaof命令后,RediS实例会进行如下操作: 保存主实例信息 主从之间建立SOCket连接 给主实例发送ping命令,等待主实例回复PorIg 进行权限验证 使用rep1conf命令给主实例发送自身的
2、监听端口、ip地址(如果设置了announce-ip)及自身支持的CaPa等信息 与主实例同步数据 主实例将接到的写命令持续传播至从实例如果该节点之前有连接的其他主实例,则该命令会执行切主操作: 断开与旧主实例复制关系 与新主实例建立复制关系 删除从实例当前所有数据 对新主实例进行复制操作数据同步当从实例首次连接主实例、执行了切主操作或者网络出现闪断后,从实例会与主实例进行数据同步。RediS中数据同步包括全量同步和部分同步两种,涉及到SYNC和PSYNC两个命令。SYNC命令在RediS2.8之前,RediS只支持SYNC命令。当收到从实例发送的SYNC命令时,主实例与从实例进行全量同步,其
3、操作流程如下:初始化:-从实例初次连接或者断线后重连主实例-主、从之间完成鉴权、保存相互监听端口、地址信息等操作全量复制- 从实例发送SYNC命令- 主实例fork出子进程执行bgsave生成RDB文件- 主实例向从发送RDB文件- 主实例在发送RDB文件期间正常处理客户端命令,并将写命令添加到从实例的输出缓存中,在发送完RDB文件后,将该部分缓存命令发送给从实例- 从实例清空数据- 从实例加载主发送的RDB文件和缓存命令- 全量复制完成PSYNC命令在RediS2.8之前,主从之间即使短暂的网络闪断也会触发全量复制,全量复制对于RediS来说是一种高10、高内存占用、高用时的操作。为了解决该
4、问题,在RediS2.8版本中引入了部分复制机制和其相应的命令PSYNC,其命令的格式为PSynCRUN.IDOFFSET。RediS使用复制偏移量、复制积压缓冲区和运行id(psync2中改为复制id)三部分来支持该命令。复制偏移量主实例和从实例双方都会分别维护一个复制偏移量,用以记载当前实例发送/接受到的命令的长度主实例每次向从实例传播N个字节的数据就将自己的复制偏移量增加N从实例每收到主实例传播来的N个数据,就将自己的复制偏移量增加N从实例每秒钟使用rep1confackOFFSET命令向主实例上报自己的复制偏移量,通过对比主从实例的复制偏移量,可以判断主从实例是否处于一致的状态。复制积
5、压缓冲区复制积压缓冲区是主实例维护的一个固定长度(参数rep1-back1og-size设置,默认为IM)的先进先出队列,当主实例进行命令传播时,不仅会将写命令同步给从实例,同时也会把写命令写入复制积压缓冲区。当从实例重新连接主实例时,主实例通过比较自身和从实例的复制偏移量,判断从实例缺少的数据是否还在复制积压缓冲区中,以此来决定对从实例进行全量同步还是部分同步。主实例运行ID主实例运行ID是一个长度为40位的16进制字符串,用于唯一标识一个RediS节点,每次在节点启动均会重新生成。从实例保存主实例的运行id标识自己复制的是哪个主实例,主实例判断PSynC命令中的run_id是否与自身的相同
6、,若不相同则进行全量复制。PSYNC2Redis在4.O版本之前使用psync命令解决了主从短暂掉线后必须进行全量复制的问题。但是在以下两个常见的运维场景仍会发生全量复制:1 .从实例重启后丢失了以前run_id和复制偏移量2 .发生了主从切换,主实例的nm_id发生了变化Redis4.0对PSYNC命令进行了升级,解决在上述两种场景下必然引起全量复制的问题。PYSNC2的命令格式为PSYNCREP1.IDOFFSET,其中REP1_ID复制ID,用以替代原先PSYNC1命令中的主实例run_id0针对从实例重启的场景在RediS关闭保存RDB文件时,会将当前实例的rep1id和OffSet保
7、存到RDB文件中,并在启动后从RDB文件加载回来。IintrdbSave1nfoAuxFie1ds(rio*rdb,intrdbf1ags,rdbSaveInfo*rsi)if(rdbSaveAuxFie1dStrStr(rdb,rep1IId,server.rep1d)-1)return-1:MMMWMif(rdbSaveAuxFie1dStr1nt(rdb,rep1ffset”,server.master_rep1_offset)-1)return-1;return1;intrdb1oadRio(rio*rdb,intrdbf1ags,rdbSave1nfo*rsi)e1seif(type
8、=RDBJ)Pe0DE_AUX)Ie1seif(!Strcasecmp(auxkey-ptr,rep1-1Iif(rsi&SdS1en(auxva1-ptr)Imemcpy(rsi-rep1_id,auxva1Irsi-rep1_id_is_set=1;e1seif(!Strcasecmp(auxkey-ptr,reif(rsi)rsi-rep1-offset=strto11(auxva1-ptr,NU11,10);针对主从切换的场景每个RediS实例均会保存两个rep1ied及它们的复制偏移量,可使用inforep1ication命令查看:127.0.0.1:6379inforep1icat
9、r01e:master1onneCted_s1aves:1MHHiastejrep1id和master_rep1_offset是当前master的复制id和复制偏移量,master_rep1id2和second_rep1_offset是本实例上一个master的复制id和对应的复制偏移量。在发生主从切换的时候,从实例发送给主实例的的rep1i_id会与主实例当前保存的master_rep1id2字段值相同,继而可以进行部分同步。IintInaSterTryPartiaIResynchronization(c1ient*c)Char*masteJrePIid=C-argv1-ptr;if(str
10、casecmp(master_rep1id,server.rep1id)&(strcasecmp(masterJeP1id,server,rep1id2)PSynC_offsetSerVer.secondJeP1id_offset)gotoneed_fu11JeSync;*Westi11havethedataours1aveisaskingr?if(!server.rep1_back1ogpsync_offset(server.rep1_back1og_off+Ser1ver.rep1_back1og_hist1en)gotoneed_fu11_resync;if(c-s1aveapa&S1A
11、VE_CAPA_PSYNC2)buf1en二SnPrintf(buf,sizeof(buf),+CONTINUEsrn”,Server.rep1id);e1sebuf1en=snprintf(buf,sizeof(buf),+CONTIN1Erif(connWrite(c-conn,buf,buf1en)!=buf1en)freeC1ientAsync(c);returnC_OK;psync_1en=addRep1yRep1IcationBack1og(c,psync_offset);PSYNC2命令流程psync2执行流程命令传播在主实例接受到命令后,首先判断是否对数据库做了改变,如果数据已经改变则将命令写入自身复制缓冲区并将命令传播给从实例,同时增加自身复制偏移量。结语RediS复制技术为RediS哨兵模式、集群模式的部署提供了支撑。从全量复制到部分复制,从PSYNC到PSYNC2,RediS不断对复制机制进行优化,但需要注意的是Redis保证的是最终一致性,故在某些极端的场景下从原理上做不到数据不丢失。-全文完-