目录
Redis的主从复制是在解决单个redis节点,可用性不高,性能有限的问题。
Redis 主从复制是指一个 Redis 服务器(主节点 Master)可以将数据同步到一个或多个 Redis 服务器(从节点 Slave)。 从节点可以接收主节点的写操作更新,并保持与主节点数据的一致性。构成主从架构的模型中,主节点负责接收查询与新增请求,而从节点只负责接收查询请求。
主从拓扑结构
一主一从
⼀主⼀从结构是最简单的复制拓扑结构,用于主节点出现宕机时从节点提供故障转移支。
当应用写命令并发量较高且需要持久化时,可以只在从节点上开启 AOF,这样既可以保证数据安全性同时也避免了持久化对主节点的性能干扰。
但需要注意的是,当主节点关闭持久化功能时,如果主节点宕机要避免动重启操作。(如果自动重启,此时没有AOF文件,就会丢失数据,进一步的主从同步会把从节点的数据也给删除了)
一主多从
⼀主多从结构(星形结构)使得应用端可以利用多个从节点实现读写分离。
对于读比重较大的场景,可以把读命令负载均衡到不同的从节点上来分担压力。
同时⼀些耗时的读命令可以指定⼀台专门的从节点执行,避免破坏整体的稳定性。
对于写并发量较高的场景,多个从节点会导致主节点写命令的多次发送从而加重主节点的负载。
树形主从
树形主从结构(分层结构)使得从节点不但可以复制主节点数据,同时可以作为其他从节点的主节点继续向下层复制。
通过引⼊复制中间层,可以有效降低住系欸按负载和需要传送给从节点的数据
量。
数据写⼊节点 A 之后会同步给 B 和 C 节点,B 节点进⼀步把数据同步给 D 和 E 节点。
当主节点需要挂载等多个从节点时为了避免对主节点的性能干扰,可以采用这种拓扑结构。
但是树形结构层次过多也可能会导致从节点与主节点数据同步延迟增大。
主从复制过程
1)保存主节点的信息,包括主节点的ip和端口。
2)从节点内部定时任务发现存在新的主节点后会一直尝试进行TCP三次握手的网络连接,直到连接成功或用户停止主从复制。
3)发送 ping 命令。连接建立成功之后,从节点通过 ping 命令确认主节点在应用层上是工作良好的。
4)权限验证。如果主节点设置了 requirepass 参数,则需要密码验证,从节点通过配置 masterauth参数来设置密码。如果验证失败,则从节点的复制将会停止。
5)同步数据集,主从复制的关键操作,分为全量复制和部分复制。
6)命令持续复制,当从节点复制了主节点的所有数据之后,针对之后的修改命令,主节点会持续的把命令发送给从节点,从节点执行修改命令,保证主从数据的⼀致性。
主从复制原理
Redis 使用 psync 命令完成主从数据同步,同步过程分为:全量复制和部分复制。
psync语法格式
PSYNC replicationid offset
replicationid:从节点上一次同步的主节点的复制 ID,如果是第一次同步,用 ?
。
offset:从节点已接收的数据偏移量,如果没有数据,用 -1
。
psync执行流程
1)从节点发送 psync 命令给主节点,replid 和 offset 的默认值分别是 ? 和 -1。 2)主节点根据 psync 参数和自身数据情况决定响应结果: 如果回复 +FULLRESYNC replid offset,则从节点需要进⾏全量复制流程。 如果回复 +CONTINEU,从节点进行部分复制流程。 如果回复 -ERR,说明 Redis 主节点版本过低,不支持 psync 命令。从节点可以使用 sync 命令进行全量复制。
全量复制
全量复制:⼀般用于初次复制场景,Redis 早期支持的复制功能只有全量复制,它会把主节点全部数据⼀次性发送给从节点,当数据量较大时,会对主从节点和网络造成很大的开销。
1)从节点发送 psync 命令给主节点进行数据同步,由于是第⼀次进行复制,从节点没有主节点的运行 ID 和复制偏移量,所以发送 psync ? -1。
2)主节点根据命令,解析出要进行全量复制,回复 +FULLRESYNC 响应。
3)从节点接收主节点的运行信息进行保存。
4)主节点执行 bgsave 进行 RDB 文件的持久化。
5)主节点发送 RDB 文件给从节点,从节点保存 RDB 数据到本地硬盘。
6)主节点将从生成 RDB 到接收完成期间执行的写命令,写入缓冲区中,等从节点保存完 RDB 文件后,主节点再将缓冲区内的数据补发给从节点,补发的数据仍然按照 rdb 的⼆进制格式追加写入到收到的 rdb 文件中,保持主从⼀致性。
7)从节点清空自身原有旧数据。
8)从节点加载 RDB 文件得到与主节点⼀致的数据。
9)如果从节点加载 RDB 完成之后,并且开启了 AOF 持久化功能,它会进行 bgrewrite 操作,得到最近的 AOF 文件。
以上redis的默认模式为有磁盘复制,整个过程可能会造成比较大的磁盘IO开销,因此也引入了另一种无磁盘复制:
主节点在执行RDB生成流程时, 不会生成 RDB文件到磁盘中了, 而是直接把生成的RDB数据通过网络发送给从节点,这样就节省了⼀系列的写硬盘和读硬盘的操作开销。即使引入了无磁盘模式,性能会更好,但传输中断代价大。
部分复制
部分复制:用于处理在主从复制中因网络闪断等原因造成的数据丢失场景,当从节点再次连上主节点后,如果条件允许,主节点会补发数据给从节点。因为补发的数据远小于全量数据,可以有效避免全量复制的过高开销。
1)当主从节点之间出现网络中断时,如果超过 repl-timeout 时间,主节点会认为从节点故障并中断复制连接。
2)主从连接中断期间主节点依然响应命令,但这些复制命令都因网络中断无法及时发送给从节点,所以暂时将这些命令滞留在复制积压缓冲区中。
3)当主从节点网络恢复后,从节点再次连上主节点。
4)从节点将之前保存的复制ID replicationid 和 复制偏移量 offset 作为 psync 的参数发送给主节点,请求进行部分复制。
5)主节点接到 psync 请求后,进行必要的验证。随后根据 offset 去复制积压缓冲区查找合适的数据,并响应 +CONTINUE 给从节点。
6)主节点将需要从节点同步的数据发送给从节点,最终完成⼀致性。
注意:因积压缓冲区空间有限,如果当前从节点需要的数据, 已经超出了主节点的积压缓冲区的范围, 则无法进行部分复制, 只能全量复制了
实时复制
主从节点在建立复制连接后,主节点会把自己收到的修改操作 , 通过tcp 长连接的方式, 源源不断的传输给从节点,从节点就会根据这些请求来同时修改自身的数据. 从而保持和主节点数据的⼀致性。
心跳包机制:为了确保在进行实时复制的时候,连接处于可用状态,redis利用心跳包机制来判断连接是否正常。
主节点默认每隔10秒给从节点发送一个ping命令,从节点收到就返回pong。
从节点默认每隔1秒就给主节点发起一个特定的请求,就会上报当前从节点复制数据的进度(offset)。