为什么需要主从架构
单节点Redis的并发能力是有上限的,想进一步提高Redis的并发能力,就需要搭建Redis主从集群,实现读写分离。
上图为主从集群的架构图,master为集群中的主节点负责redis的写操作,slave为集群中的从节点负责redis的读操作,从而实现读写分离,解决Redis单点故障的问题。
主从节点数据同步的原理
主从数据同步分为增量同步和全量同步。
- 全量同步:主从节点第一次同步数据。
- 增量同步:主从节点有过同步数据的记录,从节点的数据落后于主节点。
下图为全量同步的原理图:
结合上图,介绍一下全量同步的流程:
- slave节点第一次连接请求数据同步,并携带replid、offset参数
- master节点判断自己的replid是否于slave节点的replid一致
- 如不一致则返回主节点的replid、offset给slave节点
- 执行bgsave,生成RDB文件,发送RDB文件给slave节点,repl_baklog则会记录生成RDB文件期间所有的写命令(主从数据的差集)
- slave节点加载RDB文件
- 发送repl_baklog的写命令给slave节点
- slave节点执行repl_baklog的写命令
下面对几个陌生名词进行解释:
replid:是数据集的标记,id一致则说明是同一数据集。每一个master都有唯一的replid,slave则会继承master节点的replid
offset:偏移量,随着记录在repl_baklog中的数据增多而逐渐增大。slave完成同步时也会记录当前同步的offset。如果slave的offset小于master的offset,说明slave数据落后于master,需要更新。
repl_baklog:是一个定长的环形数组(下图),master指向的是主节点数据的offset,slave指向的是从节点数据的offset,红色部分记录的是主节点和从节点数据差异,repl_backlog简单的说就是记录主从节点数据差集的缓冲区,如果数组内容满了就会从头覆盖前面的内容。
下图为全量同步的原理图:
结合上图,介绍一下增量同步的流程:
- slave节点重启后请求数据同步,并携带replid、offset参数
- master节点判断自己的replid是否于slave节点的replid一致
- 如一致返回主节点的replid、offset给slave节点
- 在repl_baklog中获取主从节点数据的差集,并把差集数据的命令发送给slave节点
- slave节点执行命令,实现增量同步
哨兵
哨兵的作用:Redis提供了哨兵(Sentinel)机制来实现主从集群的自动故障恢复。哨兵的结构如下图所示
- 监控:Sentinel 会不断检查您的master和slave是否按预期工
- 自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主
- 通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端
Sentinel如何判断一个redis实例是否健康?
原理:Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令
- 主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线。
- 客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线。quorum值最好设置成超过Sentinel实例数量的一半。(在Redis的配置文件中可以设置quorum)
Sentinel在mster节点发生故障时如何选举新的master节点?
一旦发现master故障,sentinel需要在salve中选择一个作为新的master,下面为选举的步骤:
- 首先会判断slave节点与master节点断开时间长短,如果超过指定值(down-after-milliseconds * 10)则会排除该slave节点。
- 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举。
- 如果slave-prority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高。
- 最后是判断slave节点的运行id大小,越小优先级越高。(该id是Redis给每个示例都会分配的id)
Sentinel如何实现故障转移?
当选中了其中一个slave为新的master后(例如slave1),下面为故障的转移的步骤:
- sentinel给备选的slave1节点发送slaveof no one命令,让该节点成为master。
- sentinel给所有其它slave发送命令,通知其他的slave新的master节点为slave1,开始从新的master上同步数据。
- 最后,sentinel将故障节点的master标记为slave,当故障节点恢复后会自动成为slave节点。