我们使用redis的时候为了预防单点故障,通常要做高可用设计,redis主从架构就是一种防止redis主节点宕机启用从节点的高可用设计方案。下面我们看一下redis主从架构的设计原理。
Redis 主从架构
单机的 Redis,能够承载的 QPS 大概就在上万到几万不等。对于缓存来说,一般都是用来支撑读高并发的。因此架构做成主从(master-slave)架构,一主多从,主负责写,并且将数据复制到其它的 slave 节点,从节点负责读。所有的读请求全部走从节点。这样也可以很轻松实现水平扩容,支撑读高并发。
heartbeat
主从节点互相都会发送 heartbeat 信息。
master 默认每隔 10 秒发送一次 heartbeat,slave node 每隔 1 秒发送一个 heartbeat。
Redis replication 的核心机制
- 异步复制,不过从redis2.8开始,从结点会周期性确认自己每次复制的数据量
- 一个主节点可以配置多个从结点
- 从结点可以连接其他的从结点
- 从结点复制到时候不影响主节点工作
- 从结点复制的时候也不影响自己工作,它会使用旧的数据集提供服务,复制完成是删除旧的数据加载新的数据,这个时候就会对外暂停服务了
- 从结点主要用来横向扩容,做读写分离,提供读的吞吐量
1.2 主从架构的特点
- 读写分离:写命令主节点处理、读命令从节点处理,每个节点有不同的职责,减轻主节点压力
- 负载均衡:当从节点有多台时,可以负载均衡的处理读命令,减取各个节点的压力
- 故障恢复:当主节点发生宕机时,从节点可以取代主节点成为新的主节点,提供服务(高可用基石,哨兵和集群都使用)
- 数据冗余:从节点中的数据都是主节点的冗余数据
- 水平扩容:能快速横向扩容,支持高并发
Redis 主从复制的核心原理
2.1 基本概念
runid: 节点唯一标识,用于判断主节点是否改变的字符串,重启会改变
如果根据 host+ip 定位 master node,是不靠谱的,如果 master node 重启或者数据出现了变化,那么 slave node 应该根据不同的 run id 区分。
复制缓冲区(repl_backlog_buffer): 主节点会使用复制缓冲区记录序列化后写命令操作(复制缓冲区是有一定范围的,超过范围则会覆盖之前的偏移量)
当复制缓冲区太小,由于RDB恢复数据、网络延迟等问题让从节点延时很长时间,导致offset总不在缓冲区也会造成频繁RDB方式复制数据,可以通过改变复制缓冲区大小repl-backlog-size来解决
计算公式:最优空间 = 主节点到从节点重连多少秒 * 2 * 主节点每秒最高产生写命令数量
offset: 代表复制缓冲区上的偏移量(如果主节点收到从节点带来的offset不在复制缓冲区中说明需要使用RDB文件来进行数据恢复)
如下图:
命令传播过程:
- master将自己后边接收到的命令发送给slave 执行,保持一致性。
2.2 日志复制逻辑图
2.3 复制流程
- 当启动一个 slave node 的时候,它会发送一个 PSYNC 命令给 master node。如果是第一次连接发送PSYNC ? -1命令,表示全量复制,否则发送PSYNC 命令
- 主服务器会进行一下三种回复,+FULLRESYNC 全量复制,+CONTINUE断点续传,-ERR表示主服务器版本低于2.8,不识别这个命令
主从复制的断点续传(命令传播过程)
从 Redis2.8 开始,就支持主从复制的断点续传,如果主从复制命令传播过程中,网络连接断掉了,那么可以接着上次复制的地方,继续复制下去,而不是从头开始复制一份。
-
master node 会在内存中维护一个 backlog,master 和 slave 都会保存一个 replica offset 还有一个 master run id,offset 就是保存在 backlog 中的。
-
master每次进行命令传播的时候会把命令写入复制积压缓冲区(大小默认1M,可配置)。
-
如果 master 和 slave 网络连接断掉了,slave 定期PSYNC命令发送自己的offset(默认每隔1s)尝试与master连接
-
如果 offset偏移量之后的数据仍在复制积压缓冲区,那么会执行部分同步,master向slave发生+CONTINUE回复表示将进行部分同步,否则就会执行一次 resynchronization 。
-
在部分同步过程中,master会将offset之后的所有数据发送给slave服务器从而达到数据一致。
环形复制缓冲区写满之后,slave是会丢失掉那部分被覆盖掉的数据,还是直接进行全量复制
- 一个slave如果和master断连时间过长,造成它在master复制缓冲区的offset位置上的数据已经被覆盖掉了,此时slave和master间将进行全量复制。
- 每个slave会记录自己的复制偏移量(slave_repl_offset),每个slave的复制进度也不一定相同。在和master重连进行恢复时,slave会通过psync命令把自己记录的slave_repl_offset发给master,master会根据slave各自的复制进度,来决定这个从库可以进行增量复制,还是全量复制。
命令传播过程:
- master将自己后边接收到的命令发送给slave 执行,保持一致性。