前言
前面学完里主从复制,虽然主从复制确保里数据的安全,且我们可以实现读写分离,从节点只读,主节点负责写,这样可以分摊主节点的压力。但是又一个问题,如果主节点出现了问题就需要我们手动故障转移,需要写很多脚本去帮助我们实现。另一个存在的问题是我们主从复制时只能一主多从,所以写数据,和存储数据就会有很大的局限。
主从复制 —— 手动处理故障
这里我们模拟一下故障场景,假设现在有一主两从,master
,slave1
,slave2
。
假设master
宕机了,我们首先需要接触slave
和master
的主从关系,发送命令``slaveof no one
,之后随便找个slave
节点,假设让salve1去发送slave of new master
去把salve2
当作新的master
当作新的主节点,这样就完成故障转移了。
上面过程看似可以完成故障转移,但是存在许多问题,首先你无法判断主节点是否正常,除非外部因数如停电了,但是如果发生在半夜的话就无法判断了。其次当主节点宕机之后,客户端就失去了Redis的支持,手动操作需要时间,这中间的操作数据就会丢失,且当节点多的时候这个操作是很复杂的。
Redis sentinel
为了解决上面的情况,Redis为我们提供了sentinel
组建去帮助我们自动话的管理故障,也就是说如果组节点宕机了,sentinel
就会自动的进行故障执行我们上面的操作实现故障转移。
首先看看sentinel
的架构
首先我们会创建多个sentinel
进程(一个不存储数据的Redis进程),它会对Redis节点进行监控了实现故障转移。
这里创建多了是为了防止sentinel
节点挂了,其他sentinel
节点也会顶上。
需要注意一点的是我们客户端在获取节点的时候是通过sentinel
来获取的,也就是根据sentinel
记录的信息连接。
sentinel
的故障转移
- 1 多个
sentinel
发现并确认master
有问题 - 2 选举出一个
sentinel
作为领导 - 3 选出一个
slave
作为新的master
- 4 通知其余的
slave
成为新的master
的slave
- 5 通知客户端主从变化
- 6 如果老的
master
复活,则会成为新master
的slave
一套
sentinel
可以监控多套master-salve
组合,并使用字段master-name
区分
安装和配置
在下列的测试过程只在本机进行,实际环境master
应该分布在不同机器。
最终实现完的效果为:
下面开始操作。
首先我们看看sentinel
的配置,上面说的sentinel
只是一个不存储数据的Redis进程,所以启动只是配置文件不同的区别。
主节点配置
这里就不再具体说明了
port 7000
daemonize yes
pidfile /var/run/redis-7000.pid
logfile "7000.log"
dir "/Users/huangweikun/Desktop/redis/data/"
之后我们开启3个节点,这里复制下config,把端口修改一下。然后把7000作为主节点。
sed "s/7000/7001/g" redis-7000.conf > redis-7001.conf
sed "s/7000/7002/g" redis-7000.conf > redis-7002.conf
#让7000作为`master`节点
echo "`slave`of 127.0.0.1 7000" >> redis-7001.conf
echo "`slave`of 127.0.0.1 7000" >> redis-7002.conf
启动之后使用 ps -ef | grep redis
查看状态
之后查看7000节点信息
sentinel配置
sentinel
配置文件
port 26379 #端口
dir "/Users/huangweikun/Desktop/redis/data/" #文件存储地址
daemonize yes
logfile "26379.log" #这里同样用port区分日志文件
sentinel monitor my master 127.0.0.1 7000 2 #监控的主节点名字,地址,2的意思是,我们几个sentinel认为master有问题了就开始故障转移(最好是sentinel数量/2 + 1)
sentinel down-after-milliseconds mymaster 30000 #sentinel ping master超时时间,超过这个时间之后就认为有问题
sentinel parallel-syncs mymaster 1 #开始新master的数据复制是并发复制的个数,这里为了减轻`master`压力选择一个
sentinel failover-timeout mymaster 180000 #故障转移时间
使用 redis-sentinel
启动
之后进入26379
使用info
查看节点信息
这时启动完成之后我们去查看sentinel
的配置文件会发现它重写了配置文件去记录节点信息。
我们以同样的方式启动3个sentinel
实验
到这我们就配置好了一个可以自动故障转移的示例了。
现在我们把master
节点kill看看会不会自动转移。
我们看到7001的master
节点已经变成7002了,之后重启7000节点查看状态。
sentinel
会自动监听7000节点,如果重新上线之后会变成新master
的从节点。
sentinel工作原理
sentinel
启动后会有三个定时任务。
- 1 每10秒每个
sentinel
对master
和slave
执行info- 发现
slave
节点 - 确认主从关系
- 发现
- 2 每2秒每个
sentinel
通过master
节点的channel交换信息(pub/sub)每个sentinel会订阅一个频道去接收消息
- 通过
_sentinel_:hello
频道交换 - 交互对节点对“看法”和自身信息
- 通过
- 3 每1秒每个
sentinel
对其他对sentinel
和redis执行ping- 心跳检测掌握每个redis进程的状态
- 心跳检测掌握每个redis进程的状态
主观下线和客观下线
- 主观下线:每个
sentinel
节点对Redis节点失败的“偏见”
当sentinel
去ping节点的时候如果时间超出了我们预设的值(上面配置信息有解释),sentinel
节点就会认为这个Redis节点是失败的。 - 客观下线:所有
sentinel
节点对Redis节点失败:“达成共识”(超过了配置文件里设置对值,上面配置信息有解释)
只有master节点需要客观下线
领导者选举
我们通过客观下线或者主观下线之后,我们就要选择一个sentinel
节点来完成故障转移。
sentinel
会通过发送 sentinel is-master-down-by-addr
来竞选。
- 1 每个做主观下线的
sentinel
节点向其他sentinel
节点发送命令,要求将它设置为领导者 - 2 收到命令的
sentinel
节点如果没有同意通过其他sentinel
节点发送的命令,那么将同意请求 - 3 如果该
sentinel
节点发现自己的票数已经超过来sentinel
集合的半数且超过来quorum
,那么它将成为领导者 - 4 如果此过程有多个
sentinel
节点成为领导者,那么等待一段时间重新进行选举
故障转移(sentinel领导者选取完成)
- 1 从
slave
节点中选出一个“合适的”节点作为新的master
节点。那么如何才是”合适“的节点?-
选择
slave-priority
(slave
节点优先级)最高的节点,如果存在则返回,不存在则继续我们给
slave
优先级的情况可以是:机器配置高的我们优先级可以给高,之后配置高的会成为master
节点。 -
选择复制偏移量最大的
slave
绩点(复制最完整),如果存在则返回,不存在则继续 -
选择run_id最小的
slave
节点(启动最早的节点,我们认为比较稳定)
-
- 2 对上面对
slave
节点执行slave of no one
命令让其成为master
节点 - 3 向剩余的salve节点发送命令,让他们成为新
master
节点的slave
节点 - 4 更新原来
master
节点配置为slave
,并保持对其“关注”,当其恢复后命令它去复制新的master
节点。