redis开发与运维-多节点架构

Posted on By xqw

1. 数据同步原理

过程:

(2) 从节点会建立一个socket套接字, 专门用于接受主节点发送的复制命令,
如果从节点无法建立连接, 定时任务会无限重试直到连接成功或者执行slaveof no one取消复制
(3) 发送ping命令,如果发送ping命令后, 从节点没有收到主节点的pong回复或者超时, 比如网络超时或者主节点正在阻塞无法响应命令, 从节点会断开复制连接, 下次定时任务会发起重连
(5) 同步数据集,首次会全量同步,命令有sync和psync(>=2.8),psync可以从某个节点开始同步

psync {runId} {offset} 返回:FULLRESYNC CONTINUE ERR

1. 全量复制

2. 部分复制

2. 主从

三种创建方式:

  1. 在配置文件中加入slaveof {masterHost} {masterPort} 随Redis启动生效。
  2. 在redis-server启动命令后加入–slaveof {masterHost} {masterPort}生效。
  3. 直接使用命令: slaveof {masterHost} {masterPort}生效(也可切换至另一个主节点,会清空之前节点数据)。

断开主从: slaveof no one 从节点只读: slave-read-only yes

是否往从节点立即发送: repl-disable-tcp-nodelay no (yes会默认将40ms的内容一起发送)

拓扑:一主一从 一主多从 树状主从(从节点再发给其他从节点)

特点:从节点可作为备份,提供部分读的能力
缺点:故障需要手动切换,单机的读写、存储能力受到限制

3. 哨兵

通过Redis Sentinel实现故障自动迁移,从Redis2.8版本开始才正式生产可用

Redis Sentinel与Redis主从复制模式只是多了若干Sentinel节点, 所以Redis Sentinel并没有针对Redis节点做了特殊处理

过程:

  1. 主节点出现故障,每个Sentinel节点通过定期监控发现主节点出现了故障。
  2. 多个Sentinel节点对主节点的故障达成一致, 选举出 sentinel-3节点作为领导者负责故障转移
  3. 故障迁移 (断开主节点,其他节点slave of new master)
  4. 通知: Sentinel节点会将故障转移的结果通知给应用方

1. 如何监测故障

Sentinel三个定时监控任务

  1. 每隔10秒, 每个Sentinel节点会向主节点和从节点发送info命令获取最新的拓扑结构
  2. 每隔2秒, 每个Sentinel节点会向Redis数据节点的 __sentinel__:hello 频道上发送该Sentinel节点对于主节点的判断以及当前Sentinel节点的信息, 以此来了解其他Sentinel节点以及它们对主节点的判断
  3. 每隔1秒, 每个Sentinel节点会向主节点、 从节点、 其余Sentinel节点 发送一条ping命令做一次心跳检测, 来确认这些节点当前是否可达

主观下线(上面第三个定时器超过down-after-milliseconds没有相应)
客观下线(针对主节点,根据sentinel is-master-down-by-addr命令询问其他节点对主节点的判断,超过quorum个数则认为下线了)

sentinel is-master-down-by-addr命令:

2. 如何选举领导者

客观下线后需选择一个Sentinel节点进行迁移 选举过程:

  1. 最先对主节点进行客观下线的会向其他Sentinel节点发送sentinel is-master-down-by-addr命令, 要求将自己设置为领导者
  2. 收到命令的Sentinel节点, 如果没有同意过其他Sentinel节点的sentinel is-master-down-by-addr命令, 将同意该请求, 否则拒绝。
  3. 如果该Sentinel节点发现自己的票数已经大于等于max(quorum,num(sentinels) /2+1) , 那么它将成为领导者。
  4. 如果此过程没有选举出领导者, 将进入下一次选举。

3. 如何迁移

  1. 首先需要选择一个节点作为主节点,原则: a) 过滤: “不健康”(主观下线、 断线) 、 5秒内没有回复过Sentinel节点ping响应、 与主节点失联超过down-after-milliseconds*10秒。
    b) 选择slave-priority(从节点优先级) 最高的从节点列表, 如果存在则返回, 不存在则继续。
    c) 选择复制偏移量最大的从节点(复制的最完整) , 如果存在则返回, 不存在则继续。
    d) 选择runid最小的从节点。
  2. Sentinel领导者节点会对第一步选出来的从节点执行slaveof no one命令让其成为主节点。
  3. Sentinel领导者节点会向剩余的从节点发送命令, 让它们成为新主节点的从节点, 复制规则和parallel-syncs参数有关。
  4. Sentinel节点集合会将原来的主节点更新为从节点, 并保持着对其关注, 当其恢复后命令它去复制新的主节点。

4. 如何通知客户端

故障迁移后要通知客户端切换主节点,
以jedis为例,需要配置masterName(主节点),sentinels(Sentinel节点集合)等,
根据sentinels找到主节点(sentinel get-master-addr-by-name masterName)
为每个sentinel开启一个线程,利用Redis的发布订阅功能, 每个线程订阅Sentinel节点上切换master的相关频道+switch-master

4. 集群

哨兵模式解决了故障迁移,但是没有解决主节点单机的写、存储能力受到限制

重点
1) Redis集群数据分区规则采用虚拟槽方式, 所有的键映射到16384个 槽中, 每个节点负责一部分槽和相关数据, 实现数据和请求的负载均衡。

2) 搭建集群划分三个步骤: 准备节点, 节点握手, 分配槽。 可以使用 redis-trib.rb create命令快速搭建集群。

3) 集群内部节点通信采用Gossip协议彼此发送消息, 消息类型分为: ping消息、 pong消息、 meet消息、 fail消息等。 节点定期不断发送和接受 ping/pong消息来维护更新集群的状态。 消息内容包括节点自身数据和部分其 他节点的状态数据。

4) 集群伸缩通过在节点之间移动槽和相关数据实现。 扩容时根据槽迁 移计划把槽从源节点迁移到目标节点, 源节点负责的槽相比之前变少从而达 到集群扩容的目的, 收缩时如果下线的节点有负责的槽需要迁移到其他节 点, 再通过cluster forget命令让集群内其他节点忘记被下线节点。

5) 使用Smart客户端操作集群达到通信效率最大化, 客户端内部负责计 算维护键→槽→节点的映射, 用于快速定位键命令到目标节点。 集群协议通 过Smart客户端全面高效的支持需要一个过程, 用户在选择Smart客户端时建 议review下集群交互代码如: 异常判定和重试逻辑, 更新槽的并发控制等。 节点接收到键命令时会判断相关的槽是否由自身节点负责, 如果不是则返回 重定向信息。 重定向分为MOVED和ASK, ASK说明集群正在进行槽数据迁 移, 客户端只在本次请求中做临时重定向, 不会更新本地槽缓存。 MOVED 重定向说明槽已经明确分派到另一个节点, 客户端需要更新槽节点缓存。

6) 集群自动故障转移过程分为故障发现和故障恢复。 节点下线分为主 观下线和客观下线, 当超过半数主节点认为故障节点为主观下线时标记它为 客观下线状态。 从节点负责对客观下线的主节点触发故障恢复流程, 保证集 群的可用性。

7) 开发和运维集群过程中常见问题包括: 超大规模集群带宽消耗, pub/sub广播问题, 集群节点倾斜问题, 手动故障转移, 在线迁移数据等。