哨兵模式
引入了主从结构,很大程度上减轻了主库的压力。将读key的压力分发到了从库中,但是,如果在提供服务的过程中,主库挂了。。那怎么解决呢?如果是纯读入业务,还可以提供服务,一旦有业务要写入数据,此时怎么办!!?
redis为了解决这个问题,引入了哨兵模式。
哨兵模式解决的问题就是当主库挂了后,如何切换从库充当主库,继续提供服务的问题。
哨兵就是一个进程,它的主要工作就是 监控、选择从库作为主库、通知功能
监控:哨兵模式工作时,周期性的发送ping命令给主库,从库。如果有Redis没有响应ping命令,哨兵就会判定这台redis服务已经下线,如果是从库,哨兵将它标记为离线状态。如果是主库,哨兵开始切换主库的流程。
通知:哨兵负责通知从库和新的主库建立连接,和新的主库之间进行数据同步。
通知任务很简单,选择好了新的主库,直接将新的主库的连接信息发送给其他从库就OK。
如果是因为哨兵自身的网络状况不好,长时间没有收到主库的ping命令回复,导致进行了主库的切换!!注意!主库切换是非常耗时的操作,哨兵不仅要选择一个从库作为新的主库,并且要将新的主库连接信息发送给其他从库,而且各个从库之间要与新的主库开启数据同步。想想都是非常影响性能的!
那么如何保证哨兵不会误判主库断线了呢?
Redis引入了哨兵集群,用多个哨兵对Redis实例进行判断,这样就可以避免一个哨兵可能因为自身网络不好,迟迟没有收到ping的回复,导致误判的情况。如果有多个(一半以上)哨兵都认为主库断线了!!那么才会开启 重新选择主库以及通知的流程!
那么如何选择新的主库呢?
1、首先,Redis会筛选出网络状况好的,比如断开连接次数很少的那批从库。
2、然后,redis会按照这几个要点给从库进行打分
①查看从库的优先级,我们在配置Redis的时候就可以给Redis设置不同的优先级,比如给机器性能好,内存大的redis设置高优先级。如果这一轮选出了最优者,直接使用它作为主库。
②和旧主库同步程度最高的从库作为新的主库。
用slave_repl_offset进行比较,从库之间挨个比较,找出sloave_repl_offser最大的从库,就可以得出从库的谁的同步程度最高了!如果这一轮选出了最优者,直接使用它作为主库。
③前俩轮都没有比较出最优者,那么到了第三轮,ID最小的从库得分会最高,会使用ID最小的从库作为新的主库。
主库挂了,再重新选择主库期间,业务会受到什么影响?
1、首先写的业务肯定是不能执行了,但是读取业务依然是可以执行的。
2、写任务会执行失败,因为主库负责写,此时还没有新的主库。
但是如果不想让业务受到影响?应该怎么做呢?
可以把主库切换这段时间的写业务缓存起来,等主库切换完成后,再将写入的请求分发给主库。但是这种场景只能适用于对于写入返回不敏感的业务,如果用户的写入操作迫切希望看到结果,这明显是不合适的。
哨兵既然可以组成集群,我们在配置哨兵时,只需要指定哨兵自己的IP和端口,可是哨兵之间并不知道其他哨兵的地址,是如何组成集群的呢?
哨兵集群依赖的是redis的发布订阅功能!当哨兵和redis主库建立连接后,就可以在上面发布自己的IP和端口,同时可以订阅自己感兴趣的事件,所以不同的哨兵之间依赖redis的发布订阅功能,就可以完成他们IP和端口之间的通信,组成哨兵集群!redis的发布订阅,是通过订阅频道来实现的,不同的进程通过订阅频道,就可以接收到该频道上传输过来的数据。在哨兵集群实现中,有一个专门的频道用来实现哨兵集群,所有哨兵只需要订阅这个频道,然后在上面发布自己的IP+端口号,就可以实现哨兵集群了。
那哨兵是如何获取到从库的信息呢?毕竟哨兵既要检测主库,也要检测从库啊。
主库会保留所有从库的信息,哨兵向主库发送INFO命令就可以拿到从库的所有信息了。