第15章 复制

在redis中可以通过slaveof命令或者选项,让一个服务器取复制另一个服务器

  • 旧版复制功能的实现
    • 两个操作:
      • 同步(sync)
      • 命令传播(command propagate)
  • 旧版复制功能的缺陷
    • 初次复制
    • 断线后重新复制 (效率低)
      • sync是一个非常耗费资源的操作
  • 新版复制功能的实现
    • 使用psync,它的两种模式:
      • 完整重同步
      • 部分重同步
  • 部分重同步的实现
    • 主服务器的复制偏移量
    • 从服务器的复制偏移量
    • 主服务器的复制积压缓冲区
      • 固定长度的先进先出队列,默认1MB
      • 可以根据公式second * write_size_per_second来估算
    • 服务器的运行id
  • PSYNC命令的实现
  • 复制的实现
    • 设置主服务器的地址和端口
    • 建立套接字连接
    • 发送ping命令
    • 身份验证
    • 发送端口信息
    • 同步
    • 命令传播
  • 心跳检测
    • 在命令传播阶段,从服务器默认以每秒一次的频率,向主服务器发送命令replconf ack <replication_offset>
    • 该命令有三个作用:
      • 检查主从服务器的网络连接状态
      • 辅助实现min-slave选项
        • min-slaves-to-write和min-slaves-max-lag两个选项可以防止主服务器在不安全的情况下执行写命令
      • 检测命令丢失
        • 检测到写命令丢失,则部分同步

第16章 Sentinel

由一个或多个Sentinel实例组成的Sentinel系统可以监视任意多个主从服务器

  • 启动并初始化Sentinel
    • 初始化服务器
    • 使用Sentinel专用服务器
      • 将一部分普通redis服务器的代码替换为Sentinel专用代码
        • sentinel.c/REDIS_SENTINEL_PORT
        • sentinel.c/sentinelcmds
    • 初始化Sentinel状态
      • sentinel.c/sentinelState
    • 初始化Sentinel状态的masters字典
      • key: 被监视主服务器的名字
      • val:sentinel.c/sentinelRedisInstance 结构
    • 创建连向主服务器的网络连接
      • 每个被Sentinel监视的主服务器都会创建两个异步网络连接:
        • 命令连接:专门用于向主服务器发送命令、接收命令并回复
        • 订阅连接:连接专门用于订阅主服务器的__sentinel__:hello屏幕
        • 同时解释了为什么
  • 获取主服务器信息
    • Sentinel默认十秒一次向被监视的主服务器发送INFO命令
  • 获取从服务器信息
    • 十秒一次
  • 向主服务器和从服务器发送信息
    • Sentinel会以两秒一次的频率向所有主从服务器发送publish __sentinel__:hello "<s_ip>,<s_port>,<s_runid>,<s_epoch>,<m_name>,<m_ip>,<m_port>,<m_epoch>"
  • 接收来自主服务器和从服务器的频道信息
    • intro
      • 当Sentinel与一个主从服务器建立订阅连接后,就会发送subscribe __sentinel__:hello
      • 通过命令连接发送信息到频道
      • 通过订阅连接从频道中接收信息
      • 如果有多个Sentinel监视同一个服务器,那么只要一个Sentinel发送了一条消息,所有其他Sentinel都会收到
    • 更新Sentinels字典
      • 为主服务器创建的一个数据结构,保存了除自己以外的其他Sentinel
    • 创建连向其他Sentinel的命令连接
      • 当Sentinel通过频道信息发现了一个新的Sentinel时,它们会互相建立起命令连接,使得整体形成一个网络
      • 注意,Sentinel之间不会创建订阅
  • 检测主观下线信息
    • Sentinel以每秒一次的频率向所有与它创建命令连接的主从服务器、Sentinel发送ping命令,判断是否在线
    • 配置选项down-after-milliseconds
  • 检查客观下线信息
    • 当监视主服务器的其他Sentinel也认为该主服务器下线了(需要一定数量),则认为该主服务器客观下线
    • 发送SENTINEL is-master-down-by-addr命令询问其他Sentinel是否同意主服务器已下线
    • 接收SENTINEL is-master-down-by-addr命令
    • 发送SENTINEL is-master-down-by-addr命令的回复
  • 选举领头Sentinel
    • 当一个主服务器被判定为客观下线时,监视它的各个Sentinel会选举出一个leader对服务器进行故障转移:
      • 每个监视服务器的Sentinel都有机会成为leader
      • 不论是否成为leader,所有的Sentinel epoch都加1
      • 每个配置纪元里,所有Sentinel都有一次将某个Sentinel设置为局部leader的机会,并且设置后不可更改
      • 每个发现主服务器进入客观下线的Sentinel都会要求其他Sentinel将自己设置为局部leader
      • 优先原则:谁先申请成为leader谁优先成为leader,那么之后拒绝其他Sentinel的申请
      • 获得半数以上投票的Sentinel将成为真leader
      • 若在给定时限内没有产生leader,那么将重新选举
  • 故障转移
    • 如何在从服务器中挑选?
      • 删除下线或断线的从服务器
      • 删除5秒内没有回复leader Sentinel info命令的从服务器
      • 删除所有与已下线主服务器连接断开超过down-after-milliseconds*10毫秒的从服务器
      • 选择剩下中优先级最高的
        • 若优先级相同,则选择复制偏移量最大的
        • 若偏移量仍旧相同,那么选择id最小的

第17章 集群

  • 节点
    • cluster meet <ip> <port> 将当前节点加入到指定ip:port的集群中
    • 启动节点
      • cluster-enabled
      • 单机模式和集群模式下,单个节点的差异
    • 集群数据结构clusterNode, clusterLink, clusterState
    • cluster meet命令实现
  • 槽指派
    • 16384
    • cluster addslots 将指定范围内的槽指派给某个节点
    • 记录节点的槽指派信息clusterNode
    • 传播节点的槽指派信息
      • 一个节点需要通知其他节点自己的槽信息
    • 记录集群所有槽的指派信息
      • clusterState.slots -> clusterNode*[16384] -> clusterNode
    • cluster addslots命令的实现
      • 如果存在一个槽已经被指派,则返回错误
  • 在集群中执行命令
    • 流程
      • 检查命令要处理的数据库属于那个槽
      • 如果正好是当前节点负责,那么直接执行
      • 否则返回一个MOVED错误,重定向至正确节点
    • 计算键属于哪个槽
      • CRC16(key)
    • 判断槽是否由当前节点负责处理
    • 节点数据库的实现
      • 节点只能使用0号数据库
  • 重新分片
    • cluster-trib
  • ASK错误
    • 目标键正在被迁移,若不在当前节点,则响应ASK错误
    • cluster setslot importing命令的实现
    • cluster setslot migrating命令的实现
    • asking命令
    • ASK错误和MOVED错误的区别
  • 复制与故障转移
    • 设置从节点
    • 故障检测
      • 定期发送ping消息
    • 故障转移
    • 选举新的主节点
      • 集群的配置纪元是一个从0开始的计数器,每当某个节点发生一次故障转移,计数器加1
      • 对于每个配置纪元,集群里每个负责处理槽的主节点都有一次投票的机会,而第一个向主节点要求投票的聪姐点将获得主节点的投票
      • 当从节点发现主节点下线,会向集群广播一条clustermsg_type_failover_auth_request消息,要求所有收到并且具有投票权的主节点向这个从节点进行投票。遵守优先原则
      • 大于半数
  • 消息
    • 五种消息
      • MEET消息
      • PING消息
      • PONG消息
      • FAIL消息
      • PUBLISH消息
    • 消息头
    • MEET、PING、PONG消息的实现
    • FAIL消息的实现
    • PUBLISH消息的实现