Redis:哨兵
一、概念介绍
Redis Sentinel,即Redis哨兵,在Redis 2.8版本开始引入,实现了自动化的故障恢复,缺陷是:写操作无法负载均衡,存储能力受到单机的限制。
哨兵主要涉及到下面几个功能,核心功能是主节点的自动故障转移:
1.监控(Monitoring):
哨兵会不断地检查主节点和从节点是否运作正常。
2.自动故障转移(Automatic failover):
当主节点不能正常工作时,哨兵会开始自动故障转移操作,
它会将失效主节点的其中一个从节点升级为新的主节点,并让其他从节点改为复制新的主节点。
3.配置提供者(Configuration provider):
客户端在初始化时,通过连接哨兵来获得当前Redis服务的主节点地址。
4.通知(Notification):
哨兵可以将故障转移的结果发送给客户端。
备注:
监控和自动故障转移功能,使得哨兵可以及时发现主节点故障并完成转移;
而配置提供者和通知功能,则需要在与客户端的交互中才能体现。
(Redis官方文档)
架构图参见下图:
1.第一层的就是哨兵节点:
哨兵系统由一个或多个哨兵节点组成,哨兵节点是特殊的redis节点,不存储数据。
2.第二层的是数据节点,包括主、从节点,对于主节点和从节点来说,它们都是数据节点。
二、原理介绍
问题1: 既然哨兵节点的主要功能是故障转移,那么哨兵节点就必须要有办法知道这些节点的状态是好的还是坏的,以及哪些是主节点,哪些是从节点,对于这些,哨兵节点是如何操作的呢?
答案:每个哨兵节点维护了3个定时任务,它们分别针对不同节点并且每一个定时任务所做的事情比较固定,定时任务的功能分别如下:
1.哨兵与主从节点之间:通过向主从节点发送info命令获取最新的主从结构;
2.哨兵与哨兵之间:通过发布订阅功能获取其他哨兵节点的信息;
3.保活校验:通过向其他节点发送ping命令进行心跳检测,判断是否下线。
问题2:哨兵节点是如何知道节点下线的呢?
答案:下线在这里分为主观下线和客观下线,哨兵是根据这两种不同的下线方式来对数据节点进行下线判断的。
主观下线:在心跳检测的定时任务中,如果其他节点超过一定时间没有回复,哨兵节点就会将其进行主观下线。
客观下线:哨兵节点在对主节点进行主观下线后,会通过sentinel is-master-down-by-addr命令询问其他哨兵节点该主节点的状态;如果判断主节点下线的哨兵数量达到一定数值,则对该主节点进行客观下线。
(备注:客观下线是主节点才有的概念;如果从节点和哨兵节点发生故障,被哨兵主观下线后,不会再有后续的客观下线和故障转移操作。)
问题3: 哨兵节点是如何进行故障转移的呢?
答案:在判断出来主节点的客观下线之后,会先选举领导者哨兵节点,然后在进行故障转移。
1)选举领导者哨兵节点:当主节点被判断客观下线以后,各个哨兵节点会进行协商,选举出一个领导者哨兵节点,并由该领导者节点对其进行故障转移操作。
监视该主节点的所有哨兵都有可能被选为领导者,选举使用的算法是Raft算法,算法描述如下所示:
Raft算法的基本思路是先到先得。
即在一轮选举中,哨兵A向B发送成为领导者的申请,
如果B没有同意过其他哨兵,则会同意A成为领导者。
一般来说,哨兵选择的过程很快,谁先完成客观下线,一般就能成为领导者。
2)故障转移:
选举出的领导者哨兵,开始进行故障转移操作,该操作大体可以分为3个步骤:
1.在从节点中选择新的主节点:
选择的原则是,首先过滤掉不健康的从节点;
然后选择优先级最高的从节点(由slave-priority指定);
如果优先级无法区分,则选择复制偏移量最大的从节点;
如果仍无法区分,则选择runid最小的从节点。
2. 更新主从状态:
通过slaveof no one命令,让选出来的从节点成为主节点;
并通过slaveof命令让其他节点成为其从节点。
3. 将已经下线的主节点设置为新的主节点的从节点,
当该节点重新上线后,它会成为新的主节点的从节点。
三、使用哨兵的注意点:
1.哨兵节点的数量应不止一个,一方面增加哨兵节点的冗余,避免哨兵本身成为高可用的瓶颈;另一方面减少对下线的误判。此外,这些不同的哨兵节点应部署在不同的物理机上。
2.哨兵节点的数量应该是奇数,便于哨兵通过投票做出“决策”:领导者选举的决策、客观下线的决策等。
3.各个哨兵节点的配置应一致,包括硬件、参数等;此外,所有节点都应该使用ntp或类似服务,保证时间准确、一致。
参考资料:
https://redis.io/topics/sentinel
http://www.redis.cn
https://www.cnblogs.com/kismetv/p/9609938.html
- ASM 翻译系列第十七弹:ASM Internal ASM Disk Directory
- Windows 7下获取System权限
- ASM 翻译系列第十八弹:ASM Internal ASM file number 5
- 菜单式Shell运维脚本调试小记
- 优化Postgres-x2 GTM
- 启用某些Linux发行版的root帐号
- Linux中的完美截图工具:Deepin-ScreenShot
- ASM 翻译系列第二十弹:ASM Internal ASM file number 7
- Linux:awk命令详解
- 给已安装的Linux新增Swap交换分区
- ASM 翻译系列第二十一弹:ASM Attributes Directory
- Linux:sed命令详解
- ASM 翻译系列第二十二弹:ASM Internal ASM file number 8
- Ghost安装Win7/XP后自动恢复IP的批处理
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- Android模仿实现微博详情页滑动固定顶部栏的效果实例
- Android EventBus(普通事件/粘性事件)详解
- Android实现EventBus登录界面与传值(粘性事件)
- Android自定义LinearLayout布局显示不完整的解决方法
- android短信管理器SmsManager实例详解
- Android开发判断一个app应用是否在运行的方法详解
- 收割腾讯等十几个Offer后,揭秘进大厂的秘诀和Android技术面试题汇总!
- Flutter BLoC 异步通信、BlocBuilder的基本使用、BlocProvider的初探
- Android设备获取扫码枪扫描的内容与可能遇到的问题解决
- 3分钟短文:胆儿真肥!Laravel在命令行问用户要数据!
- 实战矿马:数据异常牵出的挖矿木马(.systemd-service.sh)
- leetcode之两个相同字符之间的最长子字符串
- 面试阿里被P8质问:ConcurrentHashMap真的线程安全吗?
- 腾讯云TKE-搭建prometheus监控(二)
- Qt音视频开发41-人脸识别嵌入式