一文让你明白Redis主从同步

今天想和大家分享有关 Redis 主从同步(也称「复制」)的内容。

我们知道,当有多台 Redis 服务器时,肯定就有一台主服务器和多台从服务器。一般来说,主服务器进行写操作,从服务器进行读操作。

那么这里有存在一个问题:从服务器如何和主服务器进行数据同步的呢?

这个问题,就是通过今天的内容:主从同步来解决的。

文章内容依旧比较干,一共 3k+ 字,建议大家静下心来专心看,文末会给大家做个简单总结归纳。

1. 如何进行主从同步

假如,现在有 2 台 Redis 服务器,地址分别是 127.0.0.1:6379 和 127.0.0.1:12345

我们在 127.0.0.1:12345 的客户端输入命令:

127.0.0.1:12345> SLAVEOF 127.0.0.6379

如此 127.0.0.1:12345 服务器就会去复制 127.0.0.1:6379 的数据。即前者是从服务器,后者为主服务器。

除了以上方式进行复制之外,还可以通过配置文件中的 slaveof 选项进行设置。

可能,求知欲爆棚的你会想知道,Redis 是怎么进行主从同步的?

ok,下面我们继续了解一下。

2. 主从同步的实现过程

主从同步分为 2 个步骤:同步和命令传播

同步:将从服务器的数据库状态更新成主服务器当前的数据库状态。(数据库状态在这篇文章开头有提到是什么意思,不清楚的小伙伴可以先看下:一文让你明白Redis持久化)

命令传播:当主服务器数据库状态被修改后,导致主从服务器数据库状态不一致,此时需要让主从数据同步到一致的过程。

上面就是主从同步 2 个步骤的作用,下面我打算稍微细说这两个步骤的实现过程。

这里需要提前说明一下:在 Redis 2.8 版本之前,进行主从复制时一定会顺序执行上述两个步骤,而从 2.8 开始则可能只需要执行命令传播即可。在下文也会解释为什么会这样?

2.1 同步

从服务器对主服务的同步操作,需要通过 sync 命令来实现,以下是 sync 命令的执行步骤:

  1. 从服务器向主服务器发送 sync 命令
  2. 收到 sync 命令后,主服务器执行 bgsave 命令,用来生成 rdb 文件,并在一个缓冲区中记录从现在开始执行的写命令。
  3. bgsave 执行完成后,将生成的 rdb 文件发送给从服务器,用来给从服务器更新数据
  4. 主服务器再将缓冲区记录的写命令发送给从服务器,从服务器执行完这些写命令后,此时的数据库状态便和主服务器一致了。

用图表示就是这样的:


image

2.1 命令传播

经过同步操作,此时主从的数据库状态其实已经一致了,但这种一致的状态的并不是一成不变的。

在完成同步之后,也许主服务器马上就接受到了新的写命令,执行完该命令后,主从的数据库状态又不一致。

为了再次让主从数据库状态一致,主服务器就需要向从服务器执行命令传播操作 ,即把刚才造成不一致的写命令,发送给从服务器去执行。从服务器执行完成之后,主从数据库状态就又恢复一致了。

这里插播一个疑问:

不知道有没有的读者觉得,当发生上述不一致的情况后,Redis 再执行同步操作不就 ok 了吗?

从效果上来说,的确是可以恢复同步,但其实没有必要。原因是实现同步的 sync 命令是一个非常消耗资源的操作,看完下图的说明,相信你肯定理解的。


image

既然同步是一个非常消耗资源的操作,那 Redis 有没有什么优化方法呢?答案当然是有的。

2.3 优化版同步操作

还记得上面说的内容吗 —— 2.8 版本开始,进行主从同步可能只需要执行命令传播即可。这个也是因为 sync 比较耗资源,从而采取的优化。

那什么时候可以这么做呢?我们先看下前提条件:

主从同步实际分 2 种情况:

  • 初次复制:从服务器第一次复制当前主服务器(PS:主服务器是有可能更换的)

  • 断线后重复制:处于命令传播阶段的主从服务器,因为网络问题而中断复制,从服务器通过自动重连,重新连接上主服务器并继续复制。

在断线后重复制的情况下,在 2.8 版本之前,会再次执行同步(sync 命令)和命令传播。

如果说,在断线期间,主服务器(已有上万键值对)只执行了几个写命令,为了让从服务器弥补这几个命令,却要重新执行 sync 来生成新的 rdb 文件,这也是非常低效的。

为了解决这个问题,2.8 开始就使用 psync 命令来代替 sync 命令去执行同步操作。

psync 具有完整重同步和部分重同步两种模式:

  • 完整重同步:用于初次复制情况,执行过程同 sync,在这不赘述了。

  • 部分重同步:用于断线后重复制情况,如果满足一定条件,主服务器只需要将断线期间执行的写命令发送给从服务器即可。

因此很明显,当主从同步出现断线后重复制的情况,psync 的部分重同步模式可以解决 sync 的低效情况。

上面的介绍中,出现了「满足一定条件」,那又是鬼什么条件呢?—— 其实就是一个偏移量的比较,具体可以继续往下看。

2.4 部分重同步的实现

部分重同步功能由以下 3 部分组成:

  • 主从服务器的复制偏移量

  • 主服务器的复制积压缓冲区

  • 服务器的运行 id(run id)

2.4.1 复制偏移量

执行复制的主从服务器都会分别维护各自的复制偏移量:

  • 主服务器每次向从服务器传播 n 个字节数据时,都会将自己的复制偏移量加 n。

  • 从服务器接受主服务器传来的数据时,也会将自己的复制偏移量加 n

举个例子:

若当前主服务器的复制偏移量为 10000,此时向从服务器传播 30 个字节数据,结束后复制偏移量为 10030。

这时,从服务器还没接收这 30 个字节数据就断线了,然后重新连接上之后,该从服务器的复制偏移量依旧为 10000,说明主从数据不一致,此时会向主服务器发送 psync 命令。

那么主服务器应该对从服务器执行完整重同步还是部分重同步呢?如果执行部分重同步的话,主服务器又如何知道同步哪些数据给从服务器呢?

以下答案都和复制积压缓冲区有关

2.4.2 复制积压缓冲区

首先,复制积压缓冲区是一个固定长度,先进先出的队列,默认 1MB。

当主服务器进行命令传播时,不仅会将命令发送给从服务器,还会发送给这个缓冲区。

因此复制积压缓冲区的构造是这样的:

偏移量 字节值
... ...
10087 *
10088 3
10089 \r
10090 \n
10091 $
10092 3
10093 \r
10094 \n
10095 s
10096 E
10097 T
... ...

当从服务器向主服务器发送 psync 命令时,还需要将自己的复制偏移量带上,主服务器就可以通过这个复制偏移量和复制积压缓冲区的偏移量进行对比。

若复制积压缓冲区存在从服务器的复制偏移量 + 1 后的数据,则进行部分重同步,否则进行完整重同步。

2.4.3 run id

运行 id 是在进行初次复制时,主服务器将会将自己的运行 id 发送给从服务器,让其保存起来。

当从服务器断线重连后,从服务器会将这个运行 id 发送给刚连接上的主服务器。

若当前服务器的运行 id 与之相同,说明从服务器断线前复制的服务器就是当前服务器,主服务器可以尝试执行部分同步;

若不同则说明从服务器断线前复制的服务器不是当前服务器,主服务器直接执行完整重同步。

花了很多笔墨,终于把部分重同步的实现写完了,最后补充一个辅助功能

2.5 心跳检测

刚才提到,主从同步有同步和命令传播 2 个步骤。

当完成了同步之后,主从服务器就会进入命令传播阶段,此时从服务器会以每秒 1 次的频率,向主服务器发送命令:REPLCONF ACK <replication_offset> ,其中 replication_offset 是从服务器当前的复制偏移量

发送这个命令主要有三个作用:

  • 检测主从服务器的网络状态

  • 辅助实现 min-slaves 选项

  • 检测命令丢失(若丢失,主服务器会将丢失的写命令重新发给从服务器)

3. 总结

终于到总结了,我们来总结一下,纪念下我这一个下午的时间。

  • 发送 SLAVEOF 命令可以进行主从同步,比如:SLAVEOF 127.0.0.6379

  • 主从同步有同步和命令传播 2 个步骤。
    同步:将从服务器的数据库状态更新成主服务器当前的数据库状态(一个消耗资源的操作)
    命令传播:当主服务器数据库状态被修改后,导致主从服务器数据库状态不一致,此时需要让主从数据同步到一致的过程

  • 主从同步分初次复制和断线后重复制两种情况
    从 2.8 版本开始,在出现断线后重复制情况时,主服务器会根据复制偏移量、复制积压缓冲区和 run id,来确定执行完整重同步还是部分重同步

  • 2.8 版本使用 psync 命令来代替 sync 命令去执行同步操作。目的是为了解决同步(sync 命令)的低效操作

欢迎大家加入粉丝群:963944895,群内免费分享Spring框架、Mybatis框架SpringBoot框架、SpringMVC框架、SpringCloud微服务、Dubbo框架、Redis缓存、RabbitMq消息、JVM调优、Tomcat容器、MySQL数据库教学视频及架构学习思维导图

写在最后:

既然看到这里了,觉得笔者写的还不错的就点个赞,加个关注呗!点关注,不迷路,持续更新!!!

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

推荐阅读更多精彩内容