Redis:浅谈Redis集群的复制原理

一、Redis的集群方案

主从复制集群:手动切换的主从复制集群、带有哨兵的HA的主从复制集群。

分片集群:客户端实现路由索引的分片集群、使用中间件代理层的分片集群、Redis自身实现的Cluster分片集群。

二、Redis主从复制的原理

1、主从复制机制

当一个master实例和一个slave实例连接正常时, master 会发送一连串的命令流来保持对slave的更新,以便于将自身数据集的改变复制给 slave , 包括客户端的写入、key的过期或被逐出等等。

当master和slave之间的连接断开之后,因为网络问题、或者是主从意识到连接超时, slave重新连接上master会尝试进行部分同步,这意味着它会尝试只获取在断开连接期间内丢失的命令流。

当无法进行部分重同步时, slave会请求进行全量重同步。这会涉及到一个更复杂的过程,例如master需要创建所有数据的快照,将之发送给 slave ,之后在数据集更改时持续发送命令流到slave。

2、主从复制的关注点

Redis使用异步复制:slave和master之间异步地确认处理的数据量。

一个master可以拥有多个slave,slave可以接受其他slave的连接。除了多个slave可以连接到同一个master之外,slave之间也可以像层叠状的结构(cascading-likestructure)连接到其他slave。自Redis4.0起,所有的sub-slave将会从master收到完全一样的复制流。

Redis复制在master侧是非阻塞的。这意味着master在一个或多个slave进行初次同步或者是部分重同步时,可以继续处理查询请求。

Redis复制在slave侧大部分也是非阻塞的。当slave进行初次同步时,它可以使用旧数据集处理查询请求,假设你在redis.conf中配置了让Redis这样做的话。在初次同步之后,旧数据集必须被删除,同时加载新的数据集。此外,你也可以配置如果复制流断开,Redis的slave会返回一个error给客户端。slave在这个短暂的时间窗口内(如果数据集很大,会持续较长时间),会阻塞到来的连接请求。自Redis4.0开始,可以配置Redis使删除旧数据集的操作在另一个不同的线程中进行,但是,加载新数据集的操作依然需要在主线程中进行并且会阻塞slave。

三、主从复制的具体过程

每一个Redis的master都有一个replicationID,这是一个较大的伪随机字符串,标记了一个给定的数据集。每个master也持有一个偏移量offset,master将自己产生的复制流发送给slave时,发送多少个字节的数据,自身的偏移量就会增加多少,目的是当有新的操作修改自己的数据集时,它可以以此更新slave的状态。偏移量offset即使在没有一个slave连接到master时,也会自增,所以基本上每一对给定的ReplicationID,offset都会标识一个master数据集的确切版本。

当slave连接到master时,它们使用PSYNC命令来发送它们记录的旧的master节点的replicationID和它们至今为止处理的偏移量。通过这种方式,master能够仅发送slave所需的增量部分。但是如果master的缓冲区中没有足够的命令积压缓冲记录,或者如果slave引用了不再知道的历史记录(replicationID),则会转而进行一个全量重同步:在这种情况下,slave会得到一个完整的数据集副本,从头开始。

下面是一个全量同步的工作细节:

master开启一个后台保存进程,以便于生产一个RDB文件。同时它开始缓冲所有从客户端接收到的新的写入命令。当后台保存完成时,master将数据集文件传输给slave,slave将之保存在磁盘上,然后加载文件到内存。再然后master会发送所有缓冲的命令发给slave。这个过程以指令流的形式完成并且和Redis协议本身的格式相同。

你可以用telnet自己进行尝试。在服务器正在做一些工作的同时连接到Redis端口并发出SYNC命令。你将会看到一个批量传输,并且之后每一个master接收到的命令都将在telnet回话中被重新发出。事实上SYNC是一个旧协议,在新的Redis实例中已经不再被使用,但是其仍然向后兼容:但它不允许部分重同步,所以现在PSYNC被用来替代SYNC。

之前说过,当主从之间的连接因为一些原因崩溃之后,slave能够自动重连。如果master收到了多个slave要求同步的请求,它会执行一个单独的后台保存,以便于为多个slave服务。

补充-无需磁盘参与的复制:正常情况下,一个全量重同步要求在磁盘上创建一个RDB文件,然后将它从磁盘加载进内存,然后slave以此进行数据同步。如果磁盘性能很低的话,这对master是一个压力很大的操作。Redis2.8.18是第一个支持无磁盘复制的版本。在此设置中,子进程直接发送RDB文件给slave,无需使用磁盘作为中间储存介质。

相关推荐
奶糖趣多多5 分钟前
Redis知识点
数据库·redis·缓存
CoderIsArt1 小时前
Redis的三种模式:主从模式,哨兵与集群模式
数据库·redis·缓存
ketil275 小时前
Redis - String 字符串
数据库·redis·缓存
王佑辉8 小时前
【redis】延迟双删策略
redis
生命几十年3万天8 小时前
redis时间优化
数据库·redis·缓存
funnyZpC8 小时前
quartz集群增强版🎉
java·分布式·开源·集群·定时任务
Shenqi Lotus9 小时前
Redis-“自动分片、一定程度的高可用性”(sharding水平拆分、failover故障转移)特性(Sentinel、Cluster)
redis·sentinel·cluster·failover·sharding·自动分片·水平拆分
java知路10 小时前
springboot 基于google 缓存,实现防重复提交
spring boot·后端·缓存
_.Switch12 小时前
Serverless架构与自动化运维
运维·python·缓存·自动化·运维开发
YMY哈13 小时前
Redis常见面试题(二)
redis