哨兵模式
如果redis的master宕机了,该如何解决?
- 关闭所有master与slave的服务
- 我们需要从slave中选择一个成为master
- 修改其他slave的配置,连接新的主
- 启动master和slave
- 全员复制N + 部分复制N
- 关闭期间的数据服务由谁来接管?
- 找一个新的master,怎么个找法?
- 修改配置后,原始的master恢复了怎么解决?
以上问题的解决方案,我们需要使用哨兵
哨兵
哨兵是一种分布式系统,用于对主从结构中的每台服务器进行监控,当出现故障时通过投票机制选择新的master并将所有的slave连接到新的master
首先,在redis中存在几个哨兵,哨兵会询问master和slave,通过ping,问他们是否宕机;也会询问其他哨兵是否存活(监控)。当一个哨兵询问master时,master并未给出回应,则他会认为该master已经宕机,也就是主观下线。他会把master未给出回应的消息通知给其他master,如果其他master在对master进行询问时,也没有回应,则说明master是真的宕机了,也别称为客观下线;
当master宕机时,需要从slave中选取一个slave来作为新的master。在这开始之前,哨兵之间会进行投票,且每个哨兵都是候选人,被选举的哨兵被称为话事人,由它来决定哪个slave称为新的master。
哨兵投票的机制: 首先哨兵会把自己的ip,端口号,竞选次数,以及自己的runid发送给其它哨兵。
在选举过程中,每个哨兵手里都有一票,且每个哨兵都想当话事人。那么哨兵就会开始抢夺,每个哨兵都会发出一条指令,告诉其他哨兵我想竞选。比如哨兵1与哨兵4发出竞选指令,哨兵2接收到指令后进行投票,那么投给谁呢。这里采用先到先得的原则,如果哨兵2最先接收到的是哨兵1的指令,则会投给哨兵1。反之,投给哨兵4。在这之间,票数最多的作为话事人,但需要注意的是,第一轮选举可能不会成功,所以可能会有第2轮,第3轮。
选取master的机制:
选举成功的哨兵会在salve中选择一个作为新的master
选取规则如下:
- 不在线的不选取
- 响应慢的不选取
- 与原来的master断开时间久的不选取
- 优先原则
- 优先级
- offset 数据多 更全
- runid 最早启动,runid越大
当新的master被选举出来后,哨兵会发送指令给其他master:
- 向新的master发送slaveof no one
- 向其他slave发送新的master的ip和端口
总结:故障转移阶段
- 发现问题,主观下线与客观下线
- 竞选话事人
- 优选新的master
- 新的master上线,其他的salve切换master,原master作为slave故障恢复后连接
企业级解决方案
- 5.1 缓存预热
场景:“宕机”服务器启动时迅速宕机
为什么会出现这种情况?
当redis服务启动时,数据并没有完全加载,正在从master或mysql中同步数据,那么大量请求来到redis,就会造成reids的崩溃。
解决方案
- 前置准备工作:
- 日常例行统计数据的访问记录,统计访问频度较高的热点数据
- 利用LRU数据的删除策略,构建数据留存队列。例如:storm和kafka配合
- 准备工作:
- 将统计的数据按级别进行分类,并根据级别,redis优先加载级别较高的热点数据
- 利用分布式多服务器同时进行数据读取,提高数据加载过程
- 热点数据主从同时预热
- 实施:
- 使用脚本程序固定触发数据预热过程
- 如果条件允许,使用CDN,效果会更好
总结:缓存预热指在系统启动前,提前将相关的缓存数据加载到redis中。避免了用户直接访问数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据
- 5.2 缓存雪崩
408:请求超时 - 场景:数据库服务器崩溃,以下场景随之而来
- 系统在平稳过程中,突然数据库的连接量激增
- 导致WebServic服务器崩溃,请求无法及时处理
- 返回用户408,500等错误页面
- 客户反复刷新页面
- 数据库服务器崩溃
- 应用服务器崩溃
- 重启应用服务器无效
- Redis服务器崩溃
- Redis集群崩溃
- 重启数据库后再次被瞬间流量倒放
- 问题产生的原因:短时间范围内,大量的Key集中过期
- 在一个相对较少的时间内,Redis存在大量过期的key
- 此时客户端请求Redis中过期的数据,Redis未命中,Redis向数据库中获取数据
- 数据库访问量激增,导致数据库无法及时处理
- Redis中大量请求被积压,不能处理,响应出现超时现象
- 数据库访问量激增,数据库崩溃
- 重启后Redis中仍无数据可用
- Redis服务器资源被严重占用,Redis服务器崩溃
- Redis集群崩溃
- 应用服务器无法接收到数据的响应,来自客户端的请求数量越来越多,应用服务器崩溃,大量408 500 爆出
- Redis,应用服务器,数据库重启,效果不理想
- 解决方案:
- LRU与LFU切换
通过数据淘汰策略,清除Redis中不常用或用的次数少的数据
LRU可以在这种情况下有效地淘汰那些最久没有被访问的失效缓存项,从而释放资源,避免进一步的雪崩
LFU可以在这种情况下有效地淘汰那些低访问频率的缓存项,从而降低它们对系统资源的占用,使高频访问的数据能够获得更好的响应时间。 - 数据有效策略调整
根据业务数据的有效期进行分类错峰,比如买手机类90分钟,食品类80分钟,化妆品类70分钟
将过期时间设置为固定时间+随机时间,稀释集中到期的key的数量,避免过期的key集中 - 超热数据永久key
对于相对来说很热门的业务数据,我们将key设置为永久状态,这样客户端访问时,不会造成key过期的现象 - 定期维护(自动+人工)
对即将过期的数据做访问量分析,确认是否延时,配合访问量统计,做热点数据的延时 - 加锁(慎用)
- 5.3 缓存击穿
- 场景:
数据库服务器崩溃,但是跟之前的场景有点不一样
- 系统平稳运行过程中
- 数据库连接量瞬间激增
- Redis服务器中无大量key过期
- Redis内存平稳,无波动
- Redis服务器CPU正常
- 数据库崩溃
- 问题产生的原因:
- Redis中某个key过期,且访问该key的数据量过大
- 多个数据请求从服务器直接压到Redis中,均未命中
- Redis在短时间内发起了大量对数据库中同一数据的访问
总结:单个key访问量过大,且key过期
- 解决方案:
- 预先设定
通俗点说就是延长key的过期时间。比如:商家的主打商品,在购物期间,加大此类信息key的过期时长。
注意:购物节不仅仅指当天,包括后续若干天,访问值呈逐渐降低 - 现场调整
现场进行检测,对流量激增的数据设置延长过期时间或设置永久key - 后台刷新数据
启动定时服务,高峰期来临之前,刷新数据有效期,确保不丢失 - 二级缓存
设置不同的失效时间,保障不会被同时淘汰就行 - 加锁
分布式锁,防止被击穿,但是要注意性能瓶颈,慎用
总结:缓存击穿就是单个高热数据过期的瞬间,访问量过大,未命中Redis,直接访问数据库,导致数据库压力过大,造成数据库系统的崩溃
- 5.4 缓存穿透
- 场景:
数据库崩溃,但和其他场景不一样
- 系统平稳运行过程中
- 应用服务器流量随时间逐渐增大
- Redis的命中率随时间逐渐降低
- Redis内存平稳,无压力
- Redis服务器CPU占用激增
- 数据库服务器压力激增
- 数据库崩溃
- 问题排查:
- Redis中大面积出现未命中
- 出现非正常的URL访问
- 问题分析:
- 获取的数据在数据库中也不存在,数据库查询未得到对应数据
- Redis获取到null数据未进行持久化,直接返回
- 下次此类数据到达重复上述过程
- 出现黑客服务器
- 解决方案:
- 缓存null
对查询结果为null的数据进行缓存(长期使用,定期清理),设定短时限,例如30-60秒,最高5分钟 - 白名单策略
提前预热各种分类数据id对应的bitmaps,id作为bitmaps的offset,相当于设置了数据白名单。当加
载正常数据时放行,加载异常数据时直接拦截(效率偏低)
使用布隆过滤器(有关布隆过滤器的命中问题对当前状况可以忽略) - 实施监控
实时监控redis命中率(业务正常范围时,通常会有一个波动值)与null数据的占比
非活动时段波动:通常检测3-5倍,超过5倍纳入重点排查对象
活动时段波动:通常检测10-50倍,超过50倍纳入重点排查对象
根据倍数不同,启动不同的排查流程。然后使用黑名单进行防控(运营) - key加密
问题出现后,临时启动防灾业务key,对key进行业务层传输加密服务,设定校验程序,过来的key校验。例如每天随机分配60个加密串,挑选2到3个,混淆到页面数据id中,发现访问key不满足规则,驳回数据访问