4. Redis哨兵模式

在主从复制我们知道slave节点宕机恢复后可以找master节点同步数据,那master节点宕机就需要另外一种方式了。Redis提供了哨兵(Sentinel)机制来实现主从集群的自动故障恢复。

4.1. Sentinel的三个作用

1. 监控:Sentinel 会不断检查您的master和slave是否按预期工作

2. 自动故障恢复:如果master故障,Sentinel会将一个slave提升为master。当故障实例恢复后也以新的master为主

3. 通知:Sentinel充当Redis客户端的服务发现来源,当集群发生故障转移时,会将最新信息推送给Redis的客户端

哨兵模式 redis 哨兵模式redis数据分片吗_redis

4.1.1.服务状态监控

Sentinel基于心跳机制监测服务状态,每隔1秒向集群的每个实例发送ping命令:

  1. 主观下线:如果某sentinel节点发现某实例未在规定时间响应,则认为该实例主观下线。
  2. 客观下线:若超过指定数量(quorum)的sentinel都认为该实例主观下线,则该实例客观下线(这时候就需要选取新的master节点了)。quorum值最好超过Sentinel实例数量的一半。

4.1.2.新master选取规则:

一旦发现master故障,sentinel需要在salve中选择一个作为新的master。

  1. 首先会判断slave节点与master节点断开时间长短,如果超过指定值(down-after-milliseconds * 10)则会排除该slave节点
  2. 然后判断slave节点的slave-priority值,越小优先级越高,如果是0则永不参与选举
  3. 如果slave-prority一样,则判断slave节点的offset值,越大说明数据越新,优先级越高
  4. 最后是判断slave节点的运行id大小,越小优先级越高。

4.1.2.故障转移:

选中了其中一个slave为新的master后,就需要进行故障转移:

  1. sentinel给备选的slave(127.0.0.1 7002)节点发送slaveof no one命令,让该节点成为master
  2. sentinel给所有其它slave发送slaveof 127.0.0.1 7002 命令,让这些slave成为新master的从节点,开始从新的master上同步数据。
  3. 最后,sentinel将故障节点标记为slave,当故障节点恢复后会自动成为新的master的slave节点

5. Redis分片集群

主从和哨兵可以解决高可用、高并发读的问题。但是依然有两个问题没有解决:

  1. 海量数据存储问题
  2. 高并发写的问题

5.1. 分片集群特征:

  1. 集群中有多个master,每个master保存不同数据
  2. 每个master都可以有多个slave节点
  3. master之间通过ping监测彼此健康状态
  4. 客户端请求可以访问集群任意节点,最终都会被转发到正确节点(根据插槽所属的节点进行转发)

5.2. 散列插槽

Redis会把每一个master节点映射到0~16383共16384个插槽(hash slot)上。数据key不是与节点绑定,而是与插槽绑定。redis会根据key的有效部分计算插槽值,分两种情况:

  1. key中包含"{}",且“{}”中至少包含1个字符,“{}”中的部分是有效部分
  2. key中不包含“{}”,整个key都是有效部分

例如:key是num,那么就根据num计算得到的slot值所属哪个节点就转发到哪个节点,如果是{itcast}num,则根据itcast计算。计算方式是利用CRC16算法得到一个hash值,然后对16384取余,得到的结果就是slot值。

思考下面两个问题:
1.Redis如何判断某个key应该在哪个实例?
分片集群将16384个插槽分配到不同的实例,可以根据key的有效部分计算哈希值,对16384取余,余数作为插槽,寻找插槽所在实例即可。
2.如何将同一类数据固定的保存在同一个Redis实例?
这一类数据使用相同的有效部分,例如key都以{typeId}为前缀

5.3. 集群伸缩

# 添加一个节点到集群中(让7001所在的集群添加一个7001的redis实例)
redis-cli --cluster add-node  127.0.0.1:7004 127.0.0.1:7001
# 新增的实例是没有分配插槽的,将部分插槽分配到新插槽
redis-cli --cluster add-node reshared 127.0.0.1:7001

# 不带下面参数,直接执行上面语句,根据控制台提示再填写相关信息,或者在指令之后带上下面的参数
--cluster-from:表示slot目前所在的节点的node ID,多个ID用逗号分隔
--cluster-to:表示需要新分配节点的node ID(貌似每次只能分配一个)
--cluster-slots:分配的slot数量


# 清空插槽
redis-cli --cluster reshard 127.0.0.1:7004 
# 下线节点
redis-cli --cluster del-node 127.0.0.1:7004 node ID
del-node后面跟着slave节点的 ip:port 和node ID

5.4.故障转移

当集群中有一个master宕机,首先是该实例与其它实例失去连接,然后是疑似宕机,最后是确定下线,自动提升一个slave为新的master:

利用cluster failover命令可以手动让集群中的某个master宕机,切换到执行cluster failover命令的这个slave节点,实现无感知的数据迁移。

哨兵模式 redis 哨兵模式redis数据分片吗_哨兵模式 redis_02

手动的Failover支持三种不同模式:

  1. 缺省:默认的流程,如图1~6
  2. force:省略了对offset的一致性校验
  3. takeover:直接执行第5歩,忽略数据一致性、忽略master状态和其它master的意见