上次阿里面试问到Redis主从复制原理,此次终于搞明白了!

1.前言程序员

Redis单节点存在单点故障,为解决单点问题,须要对Redis节点配置从节点。使用哨兵来监听主节点存活状态,若主节点挂掉,从节点能继续提供缓存功能。从节点怎样和主节点间完成数据传递?就是Redis的主从复制。redis

v2-e492d992417e3dad8e0e489446d2efb6_hd.png

2. 主从配置及做用数据库

临时配置:redis-cli进入redis从节点后,使用 --slaveof [masterIP] [masterPort]缓存

永久配置:进入从节点的配置文件redis.conf,增长slaveof [masterIP] [masterPort]网络

做用:app

1)主从配置结合哨兵模式能解决单点故障问题,提升redis可用性异步

2)从节点仅提升读的操做,主节点提供写操做。对于读多写少的情况,可给主节点配置多个从节点,从而提供响应效率socket

补充:主从复制并非redis的横向拓展,集群模式才是ide


3. 复制过程优化

1)从节点执行slaveof [masterIP] [masterPort],保存主节点信息

2)从节点中的定时任务发现主节点信息,创建和主节点的socket链接

3)从节点发送Ping信号,主节点返回Pong,两边能互相通讯

4)链接创建后,主节点将全部数据发送给从节点(数据同步

5)主节点把当前的数据同步给从节点后,便完成了复制的创建流程。接下来,主节点就会持续的把写命令发送给从节点,保证主从数据一致性

v2-2de5337ee2e53ce95509b68f2188e589_hd.png

4. 数据同步

redis 2.8 以前使用sync [runId] [offset]同步命令,redis2.8以后使用psync [runId] [offset]命令。二者不一样在于,sync命令仅支持全量复制过程,psync支持全量和部分复制;介绍同步以前先介绍几个概念:

runId:每一个redis节点启动都会生成惟一的runId,每次redis重启后,runId也会发生变化

offset:主节点和从节点都各自维护本身的主从复制偏移量offset,当主节点有写入命令时,offset=offset+命令的字节长度。从节点在收到主节点发送的命令后,也会增长本身的offset,并把本身的offset发送给主节点。这样,主节点同时保存本身的offset,从节点的offset,经过对比offset来判断主从节点数据是否一致

repl_backlog_size:保存在主节点上的一个固定长度的先进先出队列,默认大小为1MB

1)主节点发送数据给从节点过程当中,主节点还会进行一些写操做,这时候的数据存储在复制缓冲区。从节点同步主节点数据完成后,主节点将缓冲区的数据继续发送给从节点,用于部分复制;

2)主节点(master)响应写命令时,不但会把命名发送给从节点,还会写入复制积压缓冲区,用于复制命令丢失的数据补救;

psync执行流程

v2-ae1cbe4acf801b9afc15d5906047868b_hd.jpg

从节点发送psync [runId] [offset]命令,主节点有以下响应

FULLRESYNC:第一次链接,进行全量复制

CONTINUE:进行部分复制

ERR:不支持psync命令,进行全量复制

全量复制流程

v2-afc1f11850de58be07f669cb158d9cec_hd.jpg

1)从节点发送psync ? -1命令,由于第一次发送,不知道主节点的runId,因此为?,由于是第一次复制,因此offset = -1。

2)主节点发现从节点是第一次复制,变返回FULLRESYNC {runId} {offset},runId是主节点的runId,offset是主节点目前的offset。

3)从节点接收主节点信息后,保存到info中。

4)主节点在发送FULLRESYNC后,启动bgsave命令,生成RDB文件(数据持久化)。

5)6)主节点发送RDB文件给从节点。到从节点加载数据完成这段期间主节点的写命令放入缓冲区。

7)从节点清理本身的数据库数据。

8)从节点加载RDB文件,将数据保存的本身的数据库中。

9)若是从节点开启了AOF(另外一种持久化方案),从节点会异步重写aof文件。

部分复制流程

v2-795ff7ff853e54ab9c36abffb4309fab_hd.jpg

1)部分复制主要是Redis针对全量复制的太高开销作出的一种优化措施,使用psync {runId}{offset}命令实现。当从节点(slave)正在复制主节点(master)时,若是出现网络闪断或者命令丢失等异常状况时,从节点会向主节点要求补发丢失的命令数据,若是主节点的复制积压缓冲区内存将这部分数据则直接发送给从节点,这样就能够保持主从节点复制的一致性。补发的这部分数据通常远远小于全量数据。

2)主从链接中断期间主节点依然响应命令,但因复制链接中断命令没法发送给从节点,不过主节点内部存在的复制积压缓冲区,依然能够保存最近一段时间的写命令数据,默认最大缓存1MB。当从节点网络恢复后,从节点会再次连上主节点。

3)当主从链接恢复后,因为从节点以前保存了自身已复制的偏移量和主节点的运行ID。所以会把它们当作psync参数发送个主节点,要求进行部分复制操做。

4)主节点接到psync命令后首先核对参数runId是否与自身一致,若是一致,说明以前复制的是当前主节点;以后根据参数offset在自身复制积压缓冲区查找,若是偏移量以后的数据存在缓冲区中,则对从节点发送+COUTINUE响应,表示能够进行部分复制。由于缓冲区大小固定,若发生缓存溢出,则要进行全量复制。

5)主节点根据偏移量把复制积压缓冲区里的数据发送给从节点,保证主从复制进入正常状态。
欢迎你们关注个人公种浩【程序员追风】,文章都会在里面更新,整理的资料也会放在里面。

v2-234d230efcec2fb5de8044bb4f10cdfc_hd.jpg

5. 补充

Redis故障处理

若主节点挂掉后,再次重启,runid的值会变。此时从节点的发送psync命令,会提示找不到原runid,则会再进行一次全量复制。为避免这种情况,使用Redis故障转移机制,主节点挂掉后,从节点升级为主节点。如哨兵模式。

最后

欢迎你们一块儿交流,喜欢文章记得点个赞哟,感谢支持!

相关文章
相关标签/搜索