redis-4.0.x中如何解决redis重启runid变化引起的全量复制

1.run_id(服务器运行的唯一ID)

每个redis实例在启动时候,都会随机生成一个长度为40的唯一字符串来标识当前运行的redis节点,查看此id可通过命令info server查看。

当主从复制在初次复制时,主节点将自己的runid发送给从节点,从节点将这个runid保存起来,当断线重连时,从节点会将这个runid发送给主节点。主节点根据runid判断能否进行部分复制:

如果从节点保存的runid与主节点现在的runid相同,说明主从节点之前同步过,主节点会更具offset偏移量之后的数据判断是否执行部分复制,如果offset偏移量之后的数据仍然都在复制积压缓冲区里,则执行部分复制,否则执行全量复制;

如果从节点保存的runid与主节点现在的runid不同,说明从节点在断线前同步的redis节点并不是当前的主节点,只能进行全量复制;

下图为redis2.8之后的提供的psync命令执行过程:

图文说明:

如果从服务器以前没有复制过任何主服务器,或者之前执行过SLAVEOF no one命令,那么从服务器在开始一次新的复制时将向主服务器发送PSYNC ? -1命令,主动请求主服务器进行完整重同步(因为这时不可能执行部分重同步);

相反地,如果从服务器已经复制过某个主服务器,那么从服务器在开始一次新的复制时将向主服务器发送PSYNC <runid> <offset>命令:其中runid是上一次复制的主服务器的运行ID,而offset则是从服务器当前的复制偏移量,接收到这个命令的主服务器会通过这两个参数来判断应该对从服务器执行哪种同步操作,如何判断已经在介绍runid时进行详细说明。

根据情况,接收到PSYNC命令的主服务器会向从服务器返回以下三种回复的其中一种:

如果主服务器返回+FULLRESYNC <runid> <offset>回复,那么表示主服务器将与从服务器执行完整重同步操作:其中runid是这个主服务器的运行ID,从服务器会将这个ID保存起来,在下一次发送PSYNC命令时使用;而offset则是主服务器当前的复制偏移量,从服务器会将这个值作为自己的初始化偏移量;

如果主服务器返回+CONTINUE回复,那么表示主服务器将与从服务器执行部分同步操作,从服务器只要等着主服务器将自己缺少的那部分数据发送过来就可以了;

如果主服务器返回-ERR回复,那么表示主服务器的版本低于Redis 2.8,它识别不了PSYNC命令,从服务器将向主服务器发送SYNC命令,并与主服务器执行完整同步操作。

 由此可见psync也有不足之处,当从库重启以后runid发生变化,也就意味者从库还是会进行全量复制,而在实际的生产中进行从库的维护很多时候会进行重启,而正是有由于全量同步需要主库执行快照,以及数据传输会带不小的影响。因此在4.0版本,psync命令做了改进,以下说明。

2.psync2

redis4.0新版本除了增加混合持久化,还优化了psync(以下称psync2)并实现即使redis实例重启的情况下也能实现部分同步,下面主要介绍psync2实现过程。psync2在psync1基础上新增两个复制id(可使用info replication 查看如下图):

master_replid: 复制id1(后文简称:replid1),一个长度为41个字节(40个随机串+’0’)的字符串,每个redis实例都有,和runid没有直接关联,但和runid生成规则相同。当实例变为从实例后,自己的replid1会被主实例的replid1覆盖。

master_replid2:复制id2(后文简称:replid2),默认初始化为全0,用于存储上次主实例的replid1。

在4.0之前的版本,redis复制信息完全丢失,所以每个实例重启后只能进行全量复制,到了4.0版本,主要解决了两种情况下不能进行增量复制的问题:

第一种情况:redis重启

第一步:存储复制信息

redis在关闭时,通过shutdown save,都会调用rdbSaveInfoAuxFields函数,把当前实例的repl-id和repl-offset保存到RDB文件中,当前的RDB存储的数据内容和复制信息是一致性的可通过redis-check-rdb命令查看。如下图所示:

第二步:重启后加载RDB文件中的复制信息

redis加载RDB文件,会专门处理文件中辅助字段(AUX fields)信息,把其中repl_id和repl_offset加载到实例中,分别赋给master_replid和master_repl_offset两个变量值,特别注意当从库开启了AOF持久化,redis加载顺序发生变化优先加载AOF文件,但是由于aof文件中没有复制信息,所以导致重启后从实例依旧使用全量复制!

第三步:向主库上报复制信息,判断是否进行部分同步

从实例向主库上报master_replid和master_repl_offset+1;从实例同时满足以下两条件,就可以部分重新同步,否则执行全量同步:

从实例上报master_replid串,与主实例的master_replid1或replid2有一个相等,用于判断主从未发生改变;

从实例上报的master_repl_offset+1字节,还存在于主实例的复制积压缓冲区中,用于判断从库丢失部分是否在复制缓冲区中;

第二种情况:故障切换

psync2除了解决redis重启使用部分同步外,还为解决在主库故障时候从库切换为主库时候使用部分同步机制。redis从库默认开启复制积压缓冲区功能,以便从库故障切换变化master后,其他落后该从库可以从缓冲区中获取缺少的命令。该过程的实现通过两组replid、offset替换原来的master runid和offset变量实现:

第一组:master_replid和master_repl_offset:如果redis是主实例,则表示为自己的replid和复制偏移量; 如果redis是从实例,则表示为自己主实例的replid1和同步主实例的复制偏移量。

第二组:master_replid2和second_repl_offset:无论主从,都表示自己上次主实例repid1和复制偏移量;用于兄弟实例或级联复制,主库故障切换psync。

判断是否使用部分复制条件:如果从库提供的master_replid与master的replid不同,且与master的replid2不同,或同步速度快于master; 就必须进行全量复制,否则执行部分复制。

实验如下:

启动三个实例172.20.170.155:6379(主) ,172.20.170.155:6380(从) ,172.20.170.155:6381(从)

在6379上执行info replication, 如下:

在6380上执行info replication, 如下:

在6381上执行info replication, 如下:

由上图可知, 此时6381和6380的master_replid都存的是6379的master_replid.

然后执行shutdown关闭6379实例, 在6380上执行slaveof no one, 6381上执行slaveof 172.20.170.155 6380;

此时通过info replication命令查看6380和6381的信息如下:

由上图可知6379的master_replid都被存到了master_replid2上, 表示为上一次主实例的master_replid,

这时再去查看6381的日志, 如下图:

可以看出6381切换master到6380成功, 并且增量复制也是成功的.

这就完成了故障切换下增量复制功能.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,504评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,434评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,089评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,378评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,472评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,506评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,519评论 3 413
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,292评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,738评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,022评论 2 329
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,194评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,873评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,536评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,162评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,413评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,075评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,080评论 2 352

推荐阅读更多精彩内容

  • 本篇就一下方面展开分析 如何使用主从复制? 主从复制的原理(重点是全量复制和部分复制、以及心跳机制) 实际应用中需...
    lucode阅读 991评论 0 5
  • 一、Redis主从复制 主从复制:主节点负责写数据,从节点负责读数据,主节点定期把数据同步到从节点保证数据的一致性...
    爱情小傻蛋阅读 952评论 0 0
  • Redis4.0新特性psync2(partial resynchronization version2)部分重新...
    RogerZhuo阅读 7,327评论 5 6
  • 全量复制:用于初次复制或其它无法进行部分复制的情况,将主节点中的所有数据都发送给从节点,是一个非常重型的操作,当数...
    firstsecret阅读 3,148评论 2 1
  • 今年广州的天气雨水特别多。今天又是在雨天渡过,昨晚睡得不太好,时大时小的雨弄的人心情也起起伏伏。看天气预报这段时间...
    边唱边跳阅读 87评论 0 2