深入解析Redis——主从复制与哨兵

主从复制

辅助链接 Redis 设计与实现:主从复制 | 郭宁的个人博客

Redis中,用户用户可以通过执行 SLAVEOF命令或者设置 slaveof选项,让一个服务器去复制(replicate)另一个服务器,我们称之为主从复制。被复制的服务器为主服务器(Master),进行复制的服务器为从服务器(slaver),进行复制中的主从服务器双方的数据库将保存相同的数据。

  • 旧版复制

    Redis的复制功能分为同步 sync和命令传播 command propagate两个操作。

    从服务器对主服务器的同步操作需要通过向主服务器发送sync命令来完成。

    • 从服务器向主服务器发送sync命令。
    • 收到 sync命令的主服务器执行 bgsave命令,在后台生成一个RDB文件,并使用一个缓冲区记录从现在开始执行的所有写命令。
    • 当主服务器的 bgsave命令执行完毕时,主服务器会将生成的RDB文件发送给从服务器,从服务器接收并载入这个RDB文件,将自己的数据库状态更新至主服务器执行 bgsave命令时的数据库状态。
    • 主服务器将记录在复制缓冲区里面的所有写命令发送给从服务器,从服务器执行这些写命令,将自己的数据库状态更新至主服务器数据库当前所处的状态。
    • 后续当主服务器发生修改的时候,主服务器需要对从服务器执行command propagate操作:主服务器会将自己执行的写命令,然后将这条写命令发送给从服务器执行,从服务器执行后,主从服务器的数据恢复到一致的状态。
  • 新版复制

    旧版的复制在处理断线重复制情况时,效率很低,需要全部重新复制,因此Redis采用了 psync命令来代替了 sync命令。

    psync命令具有完整重同步 full resynchronization和部分重同步 partial resynchronization两种模式:

    • full resynchronization 的执行步骤和 sync 执行复制的过程一样。
    • partial resynchronization 则用于处理断线后重复制的情况。主从服务器都会分别维持一个复制偏移量来表示各自数据的offset,当主从服务器数据一致的时候,彼此的offset应该相同。同时,主服务器还会维持一个固定长度的复制积压缓冲区(FIFO),主服务器的复制积压缓冲区里面会保存着一部分最近传播的写命令,同时记录相应的复制偏移量。当从服务器短线重连后,若从服务器offset之后的数据在缓冲区内,则执行partial resynchronization ,由主服务器向从服务器发送断线期间主服务器执行的写命令,否则执行full resynchronization
      • 复制积压缓冲区:master 进行命令传播时,会将命令发送给所有 slave,同时,写入复制积压缓冲区并记录复制偏移量。由于复制积压缓冲区的大小有限,后来的写命令进入到队列中会导致前面的写命令出列,因此复制积压缓冲区仅仅保存的是最近传播的一部分写命令。

       

     

  • 心跳检测

    在命令传播阶段,从服务器默认会以每秒一次的频率,向主服务器发送命令

    	REPLCONF ACK <replication_offset> // offset 表示复制迁移量
    

    心跳检测主要用来检测主从服务器的网络状态,辅助实现min-slaves选项 和 检测命令丢失。

    • 检测命令丢失:slave 的复制偏移量,小于 master 的复制偏移量,则master 会从 复制积压缓冲区中,取出丢失的命令,再次发给 slave 执行;上述补发数据,跟网络断线重新连接过程很相似,唯一差异:当前只是丢失命令,并 master, slaver 并没有断开网络连接,没有触发 断开网络连接的机制。

哨兵

辅助链接 Redis 设计与实现:Sentinel | 郭宁的个人博客

Sentinel 哨兵是Redis的高可用性的解决方案:由一个或多个Sentinel 实例组成的Sentinel 系统,可以监控多个 master服务器及其下属 slave服务器。在master下线后,Sentinel 将在其下属的slave中选举出一个 new master服务器,并将 old master设置为new masterslave。 当old master重连后,将作为 slave存在。

  • 初始化服务器:Sentinel 在本质上是一个以特殊模式运行的Redis服务器,它并不使用数据库,而是去监控master和slave的状态。在启动Sentinel 服务器的过程中,需要将一部分普通Redis服务器的代码替换成Sentinel 专用代码。
  • **初始化Sentinel状态:**应用一个Sentinel 专用的代码后,创建一个 sentinelState的结构来保存Sentinel 的状态。sentinelState 中的master属性保存了所有被Sentinel 监控的主服务器的相关信息。
  • 建立相关的网络连接:Sentinel 会与被监控的主服务器建立两个网络连接:命令连接和订阅连接。
    • 命令连接专门用于向主服务器发送命令,并接收命令回复
    • 订阅连接用于订阅主服务器的 _**sentinel_**:hello频道
  • 获取masterslave信息:Sentinel 默认会以每十秒一次的频率,通过命令连接向被监视的主服务器发送 INFO命令,并通过分析INFO命令的回复来获取主服务器的当前信息。通过获取的master信息可以得到其下属的slave信息。Sentinel 与每一个slave建立命令连接和订阅连接,且以相同的模式每十秒向被监视的slave 发送 INFO命令来获取状态信息。
  • 向被监视的服务器发送信息:Sentinel 会以每两秒一次的频率,通过向被监视服务器的_**sentinel_**:hello频道发送消息来向其他Sentinel 宣告自己的存在。

  • sentinel系统流程

    1. sentinel 启动时,指定其监听的 master(可以指定多个 master)
    2. sentinel 与 master 建立「命令连接」
    3. sentinel 通过与 master 建立的「命令连接」,发现 slave
    4. sentinel 与 slave 建立「命令连接」
    5. sentinel 通过与 master 建立的「命令连接」,建立「订阅连接」
    6. sentinel 通过「订阅连接」发现其他 sentinel
    7. sentinel 与其他 sentinel 建立 「命令连接」,形成 sentinel 系统
  • 几个连接的作用

    • sentinel 与 master 之间的「命令连接」:发现 slave
    • sentinel 与 slave 之间的「命令连接」:old master 下线后,设置 new master,同时,将其余 slave 设置为 new master 的 slave
    • sentinel 与 master 之间的「订阅连接」:发现同一个 master 上的其他 sentinel,形成 sentinel 系统
    • sentinel 与 slave 之间的「订阅连接」:通过订阅连接来从频道中接收信息
    • sentinel 与 sentinel 之间的「命令连接」:当某一个 old master 下线后,推举出一个领头的 sentinel,由这个 sentinel 负责进行故障迁移
  • 主观下线

    一般情况下, sentinel会以每秒一次的频率向所有与它创建了命令连接的实例发送一个 PING命令,并通过实例返回PING命令的回复来判断实例是否在线。若收到的回复是无效回复(只有 +PONG、-LOADING、-MASTERDOWN 有效)或者在一定时限内没有收到回复,sentinel会修改这个实例所对应的实例结构,在结构的 flags属性中打开 SRI_S_DOWN标识,以此来表示这个实例已经进入主观下线状态

  • 客观下线

    sentinel发现master下线之后,向其他sentinel询问master是否下线,其他 sentinel会立刻通过「命令连接」进行判断,如果超过设定数量(quorum)的 sentinel 都认为 master 已经下线,则设置master为「客观下线」,即,多个 sentinel认为的下线。

  • 故障转移

    当一个master 被判定为客观下线时,监视这个master 的所有sentinel会选举出来一个领头sentinel,主导对这个master 的故障转移。

    选举领头sentinel的方式主要是先到先得:发现master 进入到客观下线的sentinel会向其他的sentinel发送 SENTINEL is-master-down-by-addr命令,要求其他sentinel将自己设置为局部领头sentinel。当一个sentinel被半数以上的sentinel设置为局部领头sentinel,它就会被最终设置为领头sentinel,主导故障转移。

    领头sentinel会按照优先级、复制偏移量等信息选举出来一个最优新master,并向他发送 SLAVEOF no one命令,将其升级。当 新master升级完成后,领头sentinel向其他的 slave 发送 SLAVEOF命令,将其他的slave 设置为新masterslave ,最后将 旧master设置为新masterslave

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值