前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Redis 4.0 PSYNC2中second_replid_offset探究

Redis 4.0 PSYNC2中second_replid_offset探究

原创
作者头像
廖可知
发布2018-07-25 14:16:59
9490
发布2018-07-25 14:16:59
举报
文章被收录于专栏:廖可知的专栏廖可知的专栏

Redis 4.0起引入了PSYNC2同步方式,分析源码时我们注意到,server数据中增加了replid2second_replid_offset两个成员。进一步分析逻辑可知,这两个成员是在master变更后,在slave中用于保存原master的ID和已同步的数据偏移的。那他们有什么作用呢?

PSYNC2用以提高特定情况下的从机数据同步效率。比如对于以下拓补

代码语言:txt
复制
   A
   +
   |
 +---+
 |   |
 v   v
 B   C

A为master,A同步数据到B、C。当A故障后,假如B被选为新的master,C成为B的从机。在过去C需要做一次数据全同步才能重新提供服务;而支持PSYNC2后,C大概率只需要从B同步最新的自己还没有接收到的数据即可,就好像自己的master还是A,只是短暂掉线重连了一样。PSYNC2相关的详细资料网络上已有很多,本文不再赘述。

上面提到,C大概率只需要从B同步最新的自己还没有接收到的数据,那就意味着有些情况下C还是需要全同步B的的。考虑下面的情况,还是A同步数据到B、C,当A中最新数据偏移为250时A故障下线,此时B接收到的最新数据偏移为200、C为175。

代码语言:txt
复制
   +----------------+          +----------------+          +----------------+
   |                |          |                |          |                |
   |                |          |                |          |                |
   |                |          |                |          |                |
   |                |          |                |          |                |
   |                |          |                |          |                |
   |                |          |                |          |                |
   |                |          |                |          |                |
   |                |          |                |          |                |
   |                |          |                |          |                |
   |   last_byte    |          |                |          |                |
   +----------------+250       |                |          |                |
   |                |          |                |          |                |
   |                +--------> +----------------+200       |                |
   |                |          |                |          +----------------+175
   |                |          |    received    |          |                |
   |                |          |     from A     |          |    received    |
   |                |          |                |          |     from A     |
   |                |          |                |          |                |
   +----------------+          +----------------+          +----------------+
        Redis A                     Redis B                     Redis C

经过哨兵调度,B成为新的master,C成为B的从机。经过一段短暂的时间,B最新数据偏移到达300,而C从B处也接收到了所有数据。此时A恢复了,上线后被哨兵调度为B的从机。因为A之前的最新数据偏移为250,所以发送PSYNC指令请求从251开始部分同步数据。如果B不做判断从251位置开始给A发送数据,很显然A中201-250这一段数据将与B、C中 的不一致。因为A故障后,201-250的数据尚未来得及同步给B,而B在后来已经将新数据追加到从A同步来的的200字节之后了,这些数据与A中的数据是不一致的。

代码语言:txt
复制
   +----------------+          +----------------+          +----------------+
   |                |          |                |          |                |
   |                |          |                |          |                |
   |                |          |                |          |                |
   |                |          |                |          |                |
   |                |          |                |          |                |
   |                |          |                |          |                |
   |                |          |                |          |                |
   |                |          |   last byte    |          |                |
   +----------------+          +----------------+300       +----------------+300
   |  recv from B   |          |                |          |                |
   +----------------+250<---X--+    new data    |          |    received    |
   |  inconsistent  |          |                |          |     from B     |
   +----------------+          +----------------+200       |                |
   |                |          |                |          +----------------+175
   |   consistent   |          |    received    |          |                |
   |                |          |     from A     |          |    received    |
   |                |          |                |          |     from A     |
   |                |          |                |          |                |
   +----------------+          +----------------+          +----------------+
        Redis A                     Redis B                     Redis C

为了避免上述问题,B需要记住原master的ID,以及从原master获得的数据偏移。当有从机带着原master的ID来请求数据时,需要先检查请求的偏移量是否超过了自己已获得的数据量。如果是,那么从机需要丢弃所有数据并做全同步,以确保数据一致。这就是replid2second_replid_offset的作用。详见replication.c:masterTryPartialResynchronization()中这段逻辑:

代码语言:txt
复制
    /* Is the replication ID of this master the same advertised by the wannabe
     * slave via PSYNC? If the replication ID changed this master has a
     * different replication history, and there is no way to continue.
     *
     * Note that there are two potentially valid replication IDs: the ID1
     * and the ID2. The ID2 however is only valid up to a specific offset. */
    if (strcasecmp(master_replid, server.replid) && //当前server的ID不是master的ID
        (strcasecmp(master_replid, server.replid2) || //并且,自己上一个master不是从机的master 或 
         psync_offset > server.second_replid_offset)) //是同一个master但从机要求的偏移比自己接收的数据还大
    {
        /* Run id "?" is used by slaves that want to force a full resync. */
        if (master_replid[0] != '?') {
            if (strcasecmp(master_replid, server.replid) &&
                strcasecmp(master_replid, server.replid2))
            {
                serverLog(LL_NOTICE,"Partial resynchronization not accepted: "
                    "Replication ID mismatch (Slave asked for '%s', my "
                    "replication IDs are '%s' and '%s')",
                    master_replid, server.replid, server.replid2);
            } else {
                serverLog(LL_NOTICE,"Partial resynchronization not accepted: "
                    "Requested offset for second ID was %lld, but I can reply "
                    "up to %lld", psync_offset, server.second_replid_offset);
            }
        } else {
            serverLog(LL_NOTICE,"Full resync requested by slave %s",
                replicationGetSlaveName(c));
        }
        goto need_full_resync;
    }

那么,A中原来的201-250的那段数据呢?丢了呗,还能咋滴。。。要不怎么说Redis并不可靠,不要当关键存储用。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 Redis
腾讯云数据库 Redis(TencentDB for Redis)是腾讯云打造的兼容 Redis 协议的缓存和存储服务。丰富的数据结构能帮助您完成不同类型的业务场景开发。支持主从热备,提供自动容灾切换、数据备份、故障迁移、实例监控、在线扩容、数据回档等全套的数据库服务。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档