Redis 主从同步
Redis 有持久化机制,即便 Redis 重启了,可以依靠 RDB 或者 AOF⽂件对数据进⾏重新加载,但在这时,只有⼀台 Redis 服务器存储着所有 的数据,此时如果 Redis 服务器「暂时」没办法修复了,那依赖 Redis 的服务就没了,所以,为了 Redis「⾼可⽤」,现在基本都会给 Redis 做 「备份」:多启⼀台 Redis 服务器,形成「主从架构」。「从服务器」的数据由「主服务器」复制过去,主从服务器的数据是⼀致的,如果主服务器挂了,那可 以「⼿动」把「从服务器」升级为「主服务器」,缩短不可⽤时间。
「复制」也叫「同步」,在 Redis 使⽤的是「PSYNC」命令进⾏同步,该命令有两种模型:完全重同步和部分重同步,可以简单理解为:如果是第⼀ 次「同步」,从服务器没有复制过任何的主服务器,或者从服务器要复制的主服务器跟上次复制的主服务器不⼀样,那就会采⽤「完全重同步」模式进⾏复制。如果 只是由于⽹络中断,只是「短时间」断连,那就会采⽤「部分重同步」模式进⾏复制。(假如主从服务器的数据差距实在是过⼤了,还是会采⽤「完全重同步」模式 进⾏复制)。
同步的原理
主服务器要复制数据到从服务器,⾸先是建⽴Socket「连接」,这个过程会⼲⼀些信息校验啊、身份校验等事情,然后从服务器就会发「PSYNC」 命令给主服务器,要求同步(这时会带「服务器 ID」RUNID 和「复制进度」offset 参数,如果从服务器是新的,那就没有),主服务器发现这是⼀个新 的从服务器(因为参数没带上来),就会采⽤「完全重同步」模式,并把「服务器 ID」(runId) 和「复制进度」(offset) 发给从服务器,从服务器 就会记下这些信息。
随后,主服务器会在后台⽣成 RDB⽂件,通过前⾯建⽴好的连接发给从服务器,从服务器收到 RDB⽂件后,⾸先把⾃⼰的数据清空,然后对 RDB⽂件进⾏加载恢复,这个过程中,主服务器也没闲着(继续接收着客户端的请求)。主服务器把⽣成 RDB⽂件「之后修改的命令」会⽤「buffer」记 录下来,等到从服务器加载完 RDB 之后,主服务器会把「buffer」记录下的命令都发给从服务器,这样⼀来,主从服务器就达到了数据⼀致性了(复制过程 是异步的,所以数据是『最终⼀致性』)。
「部分重同步」的过程其实就是靠「offset」来进⾏部分重同步。每次主服务器传播命令的时候,都会把「offset」给到从服务器,主服务器和 从服务器都会将「offset」保存起来(如果两边的 offset 存在差异,那么说明主从服务器数据未完全同步),从服务器断连之后,就会发 「PSYNC」命令给主服务器,同样也会带着 RUNID 和 offset(重连之后,这些信息还是存在的)。
主服务器收到命令之后,看 RUNID 是否能对得 上,对得上,说明这可能以前就复制过⼀部分了,接着检查该「offset」是否在主服务器记录的 offset 还存在,(这⾥解释下,因为主服务器记录 offset 使⽤的是⼀个环形 buffer,如果该 buffer 满了,会覆盖以前的记
录)。
如果找到了,那就把从缺失的⼀部分 offer 开始,把对应的修改命令发给从服务器,如果从环形 buffer 没找到,那只能使⽤「完全重同步」模式再次进⾏主从复制了。
如果 Redis 主库挂了,需要通过「哨兵」进行「自动」的故障恢复。「哨兵」⼲的事情主要就是:监控(监控主服务器的状态)、选主(主服务器挂了, 在从服务器选出⼀个作为主服务器)、通知(故障发送消息给管理员)和配置(作为配置中⼼,提供当前主服务器的信息)。可以把「哨兵」当做是运⾏在「特殊」 模式下的 Redis 服务器,为了「⾼可⽤」,哨兵也是集群架构的。
⾸先它需要跟 Redis 主从服务器创建对应的连接(获取它们的信息),每个哨兵不断地⽤ping 命令看主服务器有没有下线,如果主服务器在「配置时 间」内没有正常响应,那当前哨兵就「主观」认为该主服务器下线了,其他「哨兵」同样也会 ping 该主服务器,如果「⾜够多」(还是看配置)的哨兵认为该主 服务器已经下线,那就认为「客观下线」,这时就要对主服务器执⾏故障转移操作。「哨兵」之间会选出⼀个「领头」,选出领头的规则也⽐较多,总的来说就是先 到先得(哪个快,就选哪个),由「领头哨兵」对已下线的主服务器进⾏故障转移。
⾸先要在「从服务器」上挑选出⼀个,来作为主服务器,(这⾥也挑选讲究,⽐ 如:从库的配置优先级、要判断哪个从服务器的复制 offset 最⼤、RunID⼤⼩、跟 master 断开连接的时⻓...),然后,以前的从服务器都需要 跟新的主服务器进⾏「主从复制」,已经下线的主服务器,再次重连的时候,需要让他成为新的主服务器的从服务器。
在主从复制和故障转移的过程中会导致数据丢失数据,从上⾯的「主从复制」流程来看,这个过程是异步的(在复制的过程中:主服务器会⼀直接收请求,然 后把修改命令发给从服务器),假如主服务器的命令还没发完给从服务器,⾃⼰就挂掉了。这时候想要让从服务器顶上主服务器,但从服务器的数据是不全的。
还有 另⼀种情况就是:有可能哨兵认为主服务器挂了,但真实是主服务器并没有挂( ⽹络抖动),⽽哨兵已经选举了⼀台从服务器当做是主服务器了,此时「客户端」还没反应过来,还继续写向旧主服务器写数据,等到旧主服务器重连的时候,已经 被纳⼊到新主服务器的从服务器了...所以,那段时间⾥,客户端写进旧主服务器的数据就丢了。上⾯这两种情况(主从复制延迟&&脑裂), 都可以通过配置来「尽可能」避免数据的丢失,(达到⼀定的阈值,直接禁⽌主服务器接收写请求,企图减少数据丢失的⻛险)。
总结
- Redis 实现⾼可⽤:
- AOF/RDB 持久化机制
- 主从架构(主服务器挂了,⼿动由从服务器顶上)
- 引⼊哨兵机制⾃动故障转义
- 主从复制原理:
- PSYNC 命令两种模式:完全重同步、部分重同步
- 完全重同步:主从服务器建⽴连接、主服务器⽣成 RDB⽂件发给从服务器、主服务器不阻塞(相关修改命令记录⾄buffer)、将修改命令发给从服务器
- 部分重同步:从服务器断线重连,发送 RunId 和 offset 给主服务器,主服务器判断 offset 和 runId,将还未同步给从服务器的 offset 相关指令进⾏发送
- 哨兵机制:
- 哨兵可以理解为特殊的 Redis 服务器,⼀般会组成哨兵集群
- 哨兵主要⼯作是监控、告警、配置以及选主
- 当主服务器发⽣故障时,会「选出」⼀台从服务器来顶上「客观下线」的服务器,由「领头哨兵」进⾏切换
- 数据丢失:
- Redis 的主从复制和故障转移阶段都有可能发⽣数据丢失问题(通过配置尽可能避免)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

上一篇: Redis 数据持久化
下一篇: 彻底找到 Tomcat 启动速度慢的元凶
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论