针对2.8以前的版本,Redis在2.8之后对从服务器重连后的数据状态同步进行了改进。改进的方向是减少全量同步(full resynchronizaztion)的发生,尽可能使用增量同步(partial resynchronization)。在2.8版本之后使用psync命令代替了sync命令来执行同步操作,psync命令同时具备全量同步和增量同步的功能:
-
全量同步与上一版本(sync)一致
-
增量同步中对于断线重连后的复制,会根据情况采取不同措施;如果条件允许,仍然只发送从服务缺失的部分数据。
2.2.2 psync如何实现
Redis为了实现从服务器断线重连后的增量同步,增加了三个辅助参数:
-
复制偏移量(replication offset)
-
积压缓冲区(replication backlog)
-
服务器运行id(run id)
2.2.2.1 复制偏移量
在主服务器和从服务器内都会维护一个复制偏移量
-
主服务器向从服务发送数据,传播N个字节的数据,主服务的复制偏移量增加N
-
从服务器接收主服务器发送的数据,接收N个字节的数据,从服务器的复制偏移量增加N
正常同步的情况如下:
通过对比主从服务器之间的复制偏移量是否相等,能够得知主从服务器之间的数据状态是否保持一致。
假设此时A/B正常传播,C从服务器断线,那么将出现如下情况:
很明显有了复制偏移量之后,从服务器C断线重连后,主服务器只需要发送从服务器缺少的100字节数据即可。但是主服务器又是如何知道从服务器缺少的是那些数据呢?
2.2.2.2 复制积压缓冲区
复制积压缓冲区是一个固定长度的队列,默认为1MB大小。当主服务器数据状态发生改变,主服务器将数据同步给从服务器的同时会另存一份到复制积压缓冲区中。
复制积压缓冲区为了能和偏移量进行匹配,它不仅存储了数据内容,还记录了每个字节对应的偏移量:
当从服务器断线重连后,从服务器通过psync命令将自己的复制偏移量(offset)发送给主服务器,主服务器便可通过这个偏移量来判断进行增量传播还是全量同步。
-
如果偏移量offset+1的数据仍然在复制积压缓冲区中,那么进行增量同步操作
-
反之进行全量同步操作,与sync一致
Redis的复制积压缓冲区的大小默认为1MB,如果需要自定义应该如何设置呢?
很明显,我们希望能尽可能的使用增量同步,但是又不希望缓冲区占用过多的内存空间。那么我们可以通过预估Redis从服务断线后重连的时间T,Redis主服务器每秒接收的写命令的内存大小M,来设置复制积压缓冲区的大小S。
S = 2 * M * T
注意这里扩大2倍是为了留有一定的余地,保证绝大部分的断线重连都能采用增量同步。
2.2.2.3 服务器运行 ID
看到这里是不是再想上面已经可以实现断线重连的增量同步了,还要运行ID干嘛?其实还有一种情况没考虑,就是当主服务器宕机后,某台从服务器被选举成为新的主服务器,这种情况我们就通过比较运行ID来区分。
-
运行ID(run id)是服务器启动时自动生成的40个随机的十六进制字符串,主服务和从服务器均会生成运行ID
-
当从服务器首次同步主服务器的数据时,主服务器会发送自己的运行ID给从服务器,从服务器会保存在RDB文件中
-
当从服务器断线重连后,从服务器会向主服务器发送之前保存的主服务器运行ID,如果服务器运行ID匹配,则证明主服务器未发生更改,可以尝试进行增量同步
-
如果服务器运行ID不匹配,则进行全量同步
2.2.3 完整的psync
完整的psync过程非常的复杂,在2.8-4.0的主从复制版本中已经做到了非常完善。psync命令发送的参数如下:
psync
当从服务器没有复制过任何主服务器(并不是主从第一次复制,因为主服务器可能会变化,而是从服务器第一次全量同步),从服务器将会发送:
psync ? -1
一起完整的psync流程如下图:
-
从服务器接收到SLAVEOF 127.0.0.1 6379命令
-
从服务器返回OK给命令发起方(这里是异步操作,先返回OK,再保存地址和端口信息)
-
从服务器将IP地址和端口信息保存到Master Host和Master Port中
-
从服务器根据Master Host和Master Port主动向主服务器发起套接字连接,同时从服务将会未这个套接字连接关联一个专门用于文件复制工作的文件事件处理器,用于后续的RDB文件复制等工作
-
主服务器接收到从服务器的套接字连接请求,为该请求创建对应的套接字连接之后,并将从服务器看着一个客户端(在主从复制中,主服务器和从服务器之间其实互为客户端和服务端)
-
套接字连接建立完成,从服务器主动向主服务发送PING命令,如果在指定的超时时间内主服务器返回PONG,则证明套接字连接可用,否则断开重连
-
如果主服务器设置了密码(masterauth),那么从服务器向主服务器发送AUTH masterauth命令,进行身份验证。注意,如果从服务器发送了密码,主服务并未设置密码,此时主服务会发送no password is set错误;如果主服务器需要密码,而从服务器未发送密码,此时主服务器会发送NOAUTH错误;如果密码不匹配,主服务器会发送invalid password错误。
-
从服务器向主服务器发送REPLCONF listening-port xxxx(xxxx表示从服务器的端口)。主服务器接收到该命令后会将数据保存起来,当客户端使用INFO replication查询主从信息时能够返回数据
-
从服务器发送psync命令,此步骤请查看上图psync的两种情况
-
主服务器与从服务器之间互为客户端,进行数据的请求/响应
-
主服务器与从服务器之间通过心跳包机制,判断连接是否断开。从服务器每个1秒向主服务器发送命令,REPLCONF ACL offset(从服务器的复制偏移量),该机制可以保证主从之间数据的正确同步,如果偏移量不相等,主服务器将会采取增量/全量同步措施来保证主从之间数据状态一致(增量/全量的选择取决于,offset+1的数据是否仍在复制积压缓冲区中)
2.3 版本4.0
Redis 2.8-4.0版本仍然有一些改进的空间,当主服务器切换时,是否也能进行增量同步呢?因此Redis 4.0版本针对这个问题做了优化处理,psync升级为psync2.0。
psync2.0 抛弃了服务器运行ID,采用了replid和replid2来代替,其中replid存储的是当前主服务器的运行ID,replid2保存的是上一个主服务器运行ID。
-
复制偏移量(replication offset)
-
积压缓冲区(replication backlog)
-
主服务器运行id(replid)
-
上个主服务器运行id(replid2)
通过replid和replid2我们可以解决主服务器切换时,增量同步的问题:
- 如果replid等于当前主服务器的运行id,那么判断同步方式增量/全量同步
- 如果replid不相等,则判断replid2是否相等(是否同属于上一个主服务器的从服务器),如果相等,仍然可以选择增量/全量同步,如果不相等则只能进行全量同步。
本文阅读参考了黄健宏老师著作《Redis设计与实现》、老钱著作《Redis深度历险》等资料
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Android移动开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Android开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip204888 (备注Android)
最后是今天给大家分享的一些独家干货:
【Android开发核心知识点笔记】
【Android思维脑图(技能树)】
【Android核心高级技术PDF文档,BAT大厂面试真题解析】
【Android高级架构视频学习资源】
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
d核心高级技术PDF文档,BAT大厂面试真题解析】**
[外链图片转存中…(img-QSvTplHG-1712759252498)]
【Android高级架构视频学习资源】
一个人可以走的很快,但一群人才能走的更远。不论你是正从事IT行业的老鸟或是对IT行业感兴趣的新人,都欢迎扫码加入我们的的圈子(技术交流、学习资源、职场吐槽、大厂内推、面试辅导),让我们一起学习成长!
[外链图片转存中…(img-G5R0NEQi-1712759252499)]