当前位置:首页 » 《随便一记》 » 正文

【Redis】Redis高可用之Sentinel哨兵模式详解(Redis专栏启动)

29 人参与  2023年04月01日 19:29  分类 : 《随便一记》  评论

点击全文阅读


?作者简介:小明java问道之路,2022年度博客之星全国TOP3,专注于后端、中间件、计算机底层、架构设计演进与稳定性建工设优化。文章内容兼具广度深度、大厂技术方案,对待技术喜欢推理加验证,就职于知名金融公司后端高级工程师。

        

? 热衷分享,喜欢原创~ 关注我会给你带来一些不一样的认知和成长。

        

? 2022博客之星TOP3 | CSDN博客专家 | 后端领域优质创作者 | CSDN内容合伙人

? InfoQ(极客邦)签约作者、阿里云专家 | 签约博主、51CTO专家 | TOP红人、华为云享专家

        

?如果此文还不错的话,还请?关注、点赞、收藏三连支持?一下博主~ 


? 文末获取联系 ?  ?? 精彩专栏推荐订阅收藏 ??

专栏系列(点击解锁)

学习路线(点击解锁)

知识定位

?Redis从入门到精通与实战?

Redis从入门到精通与实战

围绕原理源码讲解Redis面试知识点与实战

?MySQL从入门到精通?

MySQL从入门到精通

全面讲解MySQL知识与企业级MySQL实战

?计算机底层原理?

深入理解计算机系统CSAPP

以深入理解计算机系统为基石,构件计算机体系和计算机思维

Linux内核源码解析

围绕Linux内核讲解计算机底层原理与并发

?数据结构与企业题库精讲?

数据结构与企业题库精讲

结合工作经验深入浅出,适合各层次,笔试面试算法题精讲

?互联网架构分析与实战?

企业系统架构分析实践与落地

行业最前沿视角,专注于技术架构升级路线、架构实践

互联网企业防资损实践

互联网金融公司的防资损方法论、代码与实践

?Java全栈白宝书?

精通Java8与函数式编程

本专栏以实战为基础,逐步深入Java8以及未来的编程模式

深入理解JVM

详细介绍内存区域、字节码、方法底层,类加载和GC等知识

深入理解高并发编程

深入Liunx内核、汇编、C++全方位理解并发编程

Spring源码分析

Spring核心七IOC/AOP等源码分析

MyBatis源码分析

MyBatis核心源码分析

Java核心技术

只讲Java核心技术

本文目录

本文目录

本文导读

一、Redis Sentinel 哨兵模式详解

1、 什么是哨兵模式

2、哨兵模式架构详解

二、Redis Sentinel(哨兵)实现原理

1、定时监控

2、主观下线和客观下线

3、Sentinel节点选举与故障转移

三、Sentinel领导者节点选举原理

四、主节点选举原理

五、Redis接入哨兵模式实战

总结


本文导读

本文深入浅出讲解什么是Redis Sentinel 哨兵模式、哨兵模式架构。剖析Redis Sentinel实现原理,Sentinel领导者节点选举原理,主节点选举原理,最后附Redis接入哨兵模式实战。

一、Redis Sentinel 哨兵模式详解

1、 什么是哨兵模式

由于Redis的主从复制模式并不具备自动恢复功能,当主服务器关闭时,需要手动将从服务器切换到主服务器。在这个过程中,不仅需要人工干预,而且服务器将在一段时间内不可用,数据安全也将无法保证。因此,主从模式的可用性较低,不适合在线生产环境。

参考资料:【Redis】Redis高可用之Cluster主从模式详解

Redis 了一种高度可用的解决方案,即 Redis Sentinel 模式,用来弥补主从模式的不足。Sentinel可以被视为一个特殊的Redis服务器,Sentinel也可以是一个单机的或集群。Sentinel(哨兵)需要监控并获取主机的工作状态是否正常,当主机发生故障时,Sentinel将自动执行故障切换,并将其监控的从服务器升级到主服务器,以确保系统的高可用性。

哨兵节点的功能描述:

监控(Monitoring):哨兵节点会持续检查主节点和从节点是否正常运行

自动故障切换( Automatic failover) :当主节点无法正常工作时,哨兵自动故障切换操作,将故障主节点的一个从节点升级成为主节点,并让其他从节点复制新的主结点。

配置提供( Configuration provider ):当客户端初始化时,通过连接哨兵获取当前 Redis 服务的主节点地址。

通知(Notification):哨兵可以将故障结果发送给客户端。

2、哨兵模式架构详解

Redis Sentinel 模式,由 Sentinel 节点和数据节点两部分组成

Sentinel 节点(绿色):哨兵系统由一个或多个哨兵节点组成,Sentinel 节点是特殊的Redis节点,它不存储数据和监视数据节点。

数据节点(红色、黄色):主节点和从节点都是数据节点。

二、Redis Sentinel(哨兵)实现原理

Redis 哨兵模式通过哨兵节点完成对数据节点的监控、下线、故障转移。

1、定时监控

Redis Sentinel 通过三个计划的监视任务发现并监视每个节点:

1、每10秒,每个Sentinel节点将向主节点和从节点发送信息命令,以获取最新结构

2.、每2秒,每个Sentinel节点将发送_Sentinel_:hello 通道发送 Sentinel 对主节点的判断和当前Sentinel 的信息

3、每秒,每个Sentinel节点将向主节点、从节点和其他 Sentinel 发送ping命令,以进行心跳检测,以确认这些节点当前是否可访问

2、主观下线和客观下线

主观下线:哨兵节点认为某个节点有问题,客观下线:超过一定数量的哨兵节点认为主节点有问题。

主观下线,每个 Sentinel 节点将每1秒向主节点和从节点的其他 Sentinel 发送 ping 命令,以进行心跳检测。当这些节点在几毫秒后停机后无法有效响应时,Sentinel 节点将对此节点做出故障决策为主观下线。

客观下线,当Sentinel的主观下线节点是主节点时,Sentinel节点将通过 sentinel is- master-down-by-addr命令,请求其他 Sentinel 结点判断主节点。当数量超过<quorum>时,Sentinel 节点认为主节点确实存在故障,然后 Sentinel 将做出客观的下线决策

3、Sentinel节点选举与故障转移

哨兵节点之间将进行领导者选举,选择一个Sentinel 节点作为领导者,所选的Sentinel负责故障切换。

1、从节点中选择一个节点作为新的主节点

2、Sentinel领导者节点将在第一步中选择的从节点上执行 slaveof no one 命令,使其成为主节点

3、Sentinel领导者节点将向剩余的从节点发送命令,使其成为新主节点的从节点

4、Sentinel领导者节点集合会将原始主节点更新为从节点,恢复时会命令它复制新的主节点

三、Sentinel领导者节点选举原理

Redis使用了 Raft 算法 实现领导者选举。

1、每个哨兵节点都有资格成为领导者,在确认主节点主观下线时候,Sentinel节点将通过sentinel is-master-down-by-addr命令向其他Sentinel节点发送请求将自己设置为领导者。

2、如果接收到命令的 Sentinel 节点未同意过其他Sentinel的命令,它将同意该请求,否则将拒绝。

3、如果哨兵节点发现其投票数大于或等于 max(quorum,num(sentinels)/2+1),它将成为领导者。

四、主节点选举原理

首先过滤主观下线、断开连接、在5秒内未对Sentinel节点ping响应作出响应的节点。

选择具有最高从属优先级 slave-priority 的从节点列表,如果存在则返回,如果不存在则选择具有最大副本偏移量(复制的最完整)的从节点,如果存在则返回,如果不存在则继续。选择具有最小runid的从节点。

首先过滤主观下线、断线、5秒内没有回复过 Sentinel 节点ping响应、与主节点失联超过 down-after-milliseconds*10 秒的节点。

选择slave-priority(从节点优先级)最高的从节点列表,如果存在则返回,不存在则继续。选择复制偏移量最大的从节点(复制的最完整),如果存在则返回,不存在则继续。选择runid最小的从节点。

五、Redis接入哨兵模式实战

哨兵模式,基于哨兵集群实现主从切换

<bean id="configBean" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">    <property name="location"> <value>redis.properties</value> </property></bean> <!-- 哨兵配置 --><bean id="sentinelConfig" class="org.springframework.data.redis.connection.RedisSentinelConfiguration">    <constructor-arg name="master" value="${redis.masterName}"/>    <constructor-arg name="sentinelHostAndPorts">        <set>            <value>${redis.hostAndPort1}</value>            <value>${redis.hostAndPort2}</value>            <value>${redis.hostAndPort3}</value>        </set>    </constructor-arg></bean> <!-- JedisPool连接池 --><bean id="jedisPoolConfig" class="redis.clients.jedis.JedisPoolConfig">    <!-- 最大分配的对象数 -->    <property name="maxTotal" value="${redis.pool.maxActive}"/>    <!-- 最大能够保持idel状态的对象数 -->    <property name="maxIdle" value="${redis.pool.maxIdle}"/>    <!-- 当池内没有返回对象时,最大等待时间 -->    <property name="maxWaitMillis" value="${redis.pool.maxWait}"/>    <!-- 测试池化连接有效性 -->    <property name="testWhileIdle" value="${redis.pool.testWhileIdle}"/>    <property name="testOnBorrow" value="${redis.pool.testOnBorrow}"/>    <property name="minIdle" value="${redis.pool.minIdle}"/>    <property name="testOnReturn" value="${redis.pool.testOnReturn}"/>    <property name="minEvictableIdleTimeMillis" value="${redis.pool.minEvictableIdleTimeMillis}"/>    <property name="timeBetweenEvictionRunsMillis" value="${redis.pool.timeBetweenEvictionRunsMillis}"/>    <property name="softMinEvictableIdleTimeMillis" value="${redis.pool.softMinEvictableIdleTimeMillis}"/></bean> <bean id="jedisConnectionFactory" class="org.springframework.data.redis.connection.jedis.JedisConnectionFactory">    <property name="usePool" value="true"/>    <property name="password" value="${redis.pass}"/>    <property name="timeout" value="${redis.timeout}"/>    <property name="poolConfig" ref="jedisPoolConfig"/>    <constructor-arg index="0" ref="sentinelConfig"/></bean> <!--SpringRedis序列化配置 --><bean id="stringRedisSerializer" class="org.springframework.data.redis.serializer.StringRedisSerializer"/><bean id="jsonRedisSerializer" class="org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer"/> <bean id="redisTemplate" class="org.springframework.data.redis.core.RedisTemplate">    <property name="connectionFactory" ref="jedisConnectionFactory"/>    <property name="keySerializer" ref="stringRedisSerializer"/>    <property name="valueSerializer" ref="jsonRedisSerializer"/></bean><bean id="cacheExecutor" class="com.wanlitong.mcmmessage.util.cache.RedisExecutorImpl">    <property name="redisTemplate" ref="redisTemplate"/>    <property name="systemPrefix" value="${redis.systemPrefix}"/></bean>

总结


点击全文阅读


本文链接:http://zhangshiyu.com/post/57883.html

<< 上一篇 下一篇 >>

  • 评论(0)
  • 赞助本站

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

关于我们 | 我要投稿 | 免责申明

Copyright © 2020-2022 ZhangShiYu.com Rights Reserved.豫ICP备2022013469号-1