redis主从结构 -- 复制

单机redis不能满足分区容错,当主机发生单点故障的时候,redis服务就无法访问;如果主机的磁盘设备损坏,甚至有丢失数据的风险。可以通过主从结构来避免单点故障的问题,当主机不可用的时候,从机仍然保持着数据的备份。必要时,可以将从机升级为主机来对外提供服务。

主从结构的需要关注两个重要问题分别是:主从数据的一致性和主从机器的存活状态。本文主要关注主从数据的一致性,即主从复制。

redis主从结构的建立是通过在从机服务器执行SLAVEOF命令实现的,该命令让从服务器连接主服务器,并去复制主服务器的数据。下文皆以master和slave分别指代主、从服务器。


slaveof建立主从结构

1.复制功能的实现 (redis2.8以前)

复制功能包含两个阶段: 同步和命令传播

  • 同步的作用:将slave的数据库状态更新至master的当前状态
  • 命令传播的作用: slave更新状态更新后,master接收到新的客户端请求导致master状态改变时,重新使slave更新到与master一致的状态。

1.1 同步的过程

  1. slave 向 master 发送 SYNC 命令
  2. master收到slave的SYNC命令, 执行BGSAVE操作,在后台生成数据快照RDB文件, 同时使用一个复制积压缓冲区来记录从生成快照开始,执行的来自于客户端的写命令。
  3. BGSAVE完成,master 将生成的RDB文件发给slave。slave接收到该文件之后载入文件,更新自己的数据库,使数据同步到与 master 在 BGSAVE 开始时相同的状态。
  4. master将缓冲区内的所有写命令发送给 slave, slave执行这些命令,更新自己的数据库,让自己更新至当前master所处的状态


    image.png

1.2 命令传播

同步过程完成后,master收到来自客户端的写请求,执行后会出现主从状态不一致的情况。为了使二者一致,master需要将这些命令发送到slave,slave执行完这些命令,两者重新回到一致的状态。

1.3 旧版本复制的缺点

每当slave连接master的时候,都需要完成同步,同步通过BGSAVE生成master中全量数据的快照,然后将快照发送给slave。这在slave初次连接到master的时候是有必要的,但是重连情况下,真的有必要全量复制吗?
slave与master断开连接期间,如果master执行的写入命令很少,为了同步这少量的数据,做全量同步是不划算的一件事。因为BGSAVE需要在后台耗费大量的CPU、内存和磁盘IO资源,同时将全部数据发送给slave需要占用较大的网络带宽和流量,影响master对客户端请求的响应。
那么能不呢在开销较小的情况下将这些增量数据同步至重连的客户端呢?有,新版本的复制支持部分重同步就是做这件事的。

2.新版本复制功能

新版本复制功能是通过PSYNC实现的,它具有完整重同步和部分重同步两种模式。

  • 完整重同步和初次同步SYNC功能相同,slave发送命令给master,由master生成RDB文件,同时在缓冲区内保存写命令,将RDB文件和写命令发送给slave。主要用于处理初次连接时数据同步。
  • 部分重同步用于处理重连时连接断开期间master执行写入命令的同步。当然,如果产生数据量过大,导致master内存不下这么多写入命令,那么仍然要通过全量同步。

思考一下为了同步在连接丢失期间内master的写入数据,我们需要那些信息?

  1. 首先需要一个容器,记录master的写入命令。 对这个容器有以下要求:第一,不能无限大,否则写入命令就能把内存给占满了;第二,既然容量有限,那么应当优先存放最近写入的命令。基于这两个要求,可以使用有限队列,由于FIFO的特性,当队列满了之后,将头部节点给remove掉,然后在尾部添加新的数据。redis由复制积压缓冲区来承担该角色。它是一个默认大小1MB的FIFO队列。
  2. 需要master和slave在恢复连接时,二者分别执行到的最后最后一条命令在队列中的位置。redis通过复制偏移量(offset)来完成。
    • master每次向slave发送N byte的数据时,将自己的offset 加 N
    • slave每次收到master发送来的N byte数据时,将自己的offset 加 N
  3. slave向master请求重连时,master如何能保证该slave之前就是从自己这里同步的数据呢?显然需要一个身份凭证,redis通过运行Id来完成校验。即slave内需要保存master的运行Id,重连时,带上该Id,master校验这是自己的id,然后才能向slave发送增量数据,否则将其视为需要全量同步。

2.1 复制积压缓冲区

redis内复制积压缓冲区结构如图:它包含了每个字节的值和其对应的偏移量。


buffer构造

2.2服务器offset

服务器内offset如下图: master与slave最近一次命令传播之后,双方offset都在10086. 之后,slave A与master断开连接。在连接断开期间,master收到了新的命令, 之后又向slave传播了33字节数据。此时各服务器的offset状态如图。


服务器内offset

假设此时slave A请求重连, 那么他需要向master发送重连请求,并带上自己的offset和内部保存的master运行Id。master收到请求后,校验运行id,然后从buffer内查找slave offset + 1是否在buffer内,如果不在,说明这段时间内请求较多,已经将这个数据给挤出了缓冲区,那么此时就不能进行部分同步,因为这样必然要丢失数据。如果在,那么将slave offset + 1 到 master offset的数据发送给slave即可。

2.3 PSYNC命令(partial sync)

PSYNC有两种调用方式:

  • 如果服务器执行过 SLAVEOF no one 或没有复制过任何服务器, 那么他向master 发送PSYNC ? -1 命令,请求master进行完整重同步。
  • 如果该服务器复制过某个master, 则他向master发送 PSYNC <runid> <offset>命令请求部分重同步, runid为上次连接master的运行ID, offset为slave的当前偏移量。

主服务器收到PSYNC后,有两种正常返回值和异常返回:

  • +FULLRESYNC <runid> <offset> (完整重同步)和 +CONTINUE (部分重同步)。 完整同步的话,slave需要保存runid和offset,在RDB数据载入数据库之后需要将自己的初始化偏移量更新为该offset;部分同步则只需要等待master将自己缺失的部分数据发送过来,然后将offset + N。
    如果为-ERR回复,表示master版本低于Redis2.8,无法识别PSYNC请求


    PSYNC的请求和返回值

同步之后,命令传播就和旧版本如出一辙了,在此不作赘述。

总结

    1. 主从主要解决的问题: 单点故障容错,当然也可以做读写分离,不过似乎没什么必要,因为可以做集群,分散每台master的读写压力。
    1. 主从结构如何实现数据复制
    • 旧版本: SYNC + 命令传播。缺点在于每次重连都需要完整同步,而完整同步需要较大的硬件资源开销。
    • 新版本: PSYNC + 命令传播。重连时通常不希望完整同步,只需要同步在连接断开期间master的写入命令即可。此时通过复制缓冲区和主从双方的offset即可判断是否可以从buffer中取出断开期间的全部写入命令,可以的话则只需要将buffer中[slave offset + 1 , master offset]区间内的数据发送到slave即可。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容