Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案

一、集群架构

1、概念

业务发展过程中遇到的峰值瓶颈

  • redis提供的服务OPS可以达到10万/秒,当前业务OPS已经达到10万/秒
  • 内存单机容量达到256G,当前业务需求内存容量1T

使用集群的方式可以快速解决上述问题

  • 集群 :同一种服务多个节点放在一起共同对系统提供服务的过程称之为集群
  • 分布式 : 有多个不同服务集群共同对系统提供服务这个系统称之为分布式系统

集群就是使用网络将若干台计算机联通起来,并提供统一的管理方式,使其对外呈现单机的服务效果;
Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案_第1张图片

Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案_第2张图片

2、作用

  • 分散单台服务器的访问压力,实现负载均衡
  • 分散单台服务器的存储压力,实现可扩展性
  • 降低单台服务器宕机带来的业务灾难
    Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案_第3张图片

3、Redis集群原理

  • 所有的redis节点彼此互联(PING-PONG机制),内部使用二进制协议优化传输速度和带宽. 每一个redis节点, 都包含有自己的master, 以及slave
  • 集群中的节点的宕机是通过集群中超过半数的节点检测失效时才生效.
  • 客户端与redis节点直连,不需要中间proxy层. 客户端不需要连接集群所有节点,连接集群中任何一个可用节点即可
  • redis-cluster 把所有的物理节点映射到[0-16383] slot上, cluster 负责维护node<->slot<->value

Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案_第4张图片

  • 当客户端执行写(set)命令后, 会将set name zhangsan经过CRC16算法, 计算出其哈希槽的位置, 然后根据该位置存储到对应的Node节点 (redis集群中的某个节点) 内, 当执行读命令(get), 会根据槽的位置, 去指定节点内取数据; 不同key的哈希槽不同, 此时读写数据就会在不同的Node内进行操作; 实现了对Redis集群的操作;
  • 故障转移, 将宕机的master节点的 由 选举出来的slave来接管; 不会从新分配槽
  • 如果动态添加一个Node(redis节点), 此时要将其他Node的槽都分出来一些, 给新的Node; 保持对16384个槽进行均分; 将槽的value(对应key的值)也会分出去

二、Redis集群搭建

  • 判断一个是集群中的节点是否可用,是集群中的所用主节点选举过程,如果半数以上的节点认为当前节点挂掉,那么当前节点就是挂掉了,所以搭建redis集群时建议节点数最好为奇数搭建集群至少需要三个主节点,三个从节点,至少需要6个节点

1、准备工作

1、准备环境安装ruby以及redis集群依赖
  • yum install -y ruby rubygems
  • gem install redis-xxx.gem
2、在一台机器创建7个目录

Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案_第5张图片

3、每个目录复制一份配置文件

[root@localhost ~]# cp redis-4.0.10/redis.conf 7000/
[root@localhost ~]# cp redis-4.0.10/redis.conf 7001/
[root@localhost ~]# cp redis-4.0.10/redis.conf 7002/
[root@localhost ~]# cp redis-4.0.10/redis.conf 7003/
[root@localhost ~]# cp redis-4.0.10/redis.conf 7004/
[root@localhost ~]# cp redis-4.0.10/redis.conf 7005/
[root@localhost ~]# cp redis-4.0.10/redis.conf 7006/

在这里插入图片描述

4、修改不同目录配置文件(每一个Redis服务的配置都要改)
  • port 6379 … //修改端口
  • bind 0.0.0.0 //开启远程连接
  • cluster-enabled yes //开启集群模式
  • cluster-config-file nodes-port.conf //集群节点配置文件
  • cluster-node-timeout 5000 //集群节点超时时间
  • appendonly yes //开启AOF持久化
5、指定不同目录配置文件启动七个节点
  • [root@localhost bin]# ./redis-server /root/7000/redis.conf
  • [root@localhost bin]# ./redis-server /root/7001/redis.conf
  • [root@localhost bin]# ./redis-server /root/7002/redis.conf
  • [root@localhost bin]# ./redis-server /root/7003/redis.conf
  • [root@localhost bin]# ./redis-server /root/7004/redis.conf
  • [root@localhost bin]# ./redis-server /root/7005/redis.conf
  • [root@localhost bin]# ./redis-server /root/7006/redis.conf

6、查看进程
  • [root@localhost bin]# ps aux|grep redis

Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案_第6张图片

2、创建集群

1.复制集群操作脚本到bin目录中
  • [root@localhost bin]# cp /root/redis-4.0.10/src/redis-trib.rb .
2.创建集群
  • ./redis-trib.rb create --replicas 1 192.168.202.205:7000 192.168.202.205:7001 192.168.202.205:7002 192.168.202.205:7003 192.168.202.205:7004 192.168.202.205:7005

7000, 7001, 7002为主节点, 7003为7000的slave节点, 7004为7001的slave节点, 7005为7002的slave节点

3、集群创建成功出现如下提示

3、查看集群状态

1.查看集群状态 check [原始集群中任意节点] [无]
  • ./redis-trib.rb check 192.168.202.205:7000

4、操作集群

Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案_第7张图片
Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案_第8张图片
get name, 扔会去指定槽的master节点取数据
Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案_第9张图片

5、集群节点状态说明

  • 主节点
    主节点存在hash slots,且主节点的hash slots 没有交叉
    主节点不能删除, 因为删除后, hash slot就不完整了, 集群不可以操作
    一个主节点可以有多个从节点
    主节点宕机时多个副本之间自动选举主节点

  • 从节点
    从节点没有hash slots
    从节点可以删除
    从节点不负责数据的写,只负责数据的同步

当主节点kill后, 会将该主节点对应的slave节点, 充当master节点, hash slot也会被拿过去;

6、集群节点的操作

Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案_第10张图片

三、Redis企业级解决方案

相关连接: Redis中缓存雪崩、缓存穿透等问题的解决方案

  • Redis详解(十二)------ 缓存穿透、缓存击穿、缓存雪崩

1、缓存预热

  • 缓存预热就是系统启动前,提前将相关的缓存数据直接加载到缓存系统
    • 避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!
    • 用户直接查询事先被预热的缓存数据!

问题排查

  • 请求数量较高的时候, 需要缓存预热。 否则会先去查询数据库, 然后再将数据进行缓存
  • 主从之间数据吞吐量较大,数据同步操作频度较高

解决方案

  • 前置准备工作:

    • 日常例行统计数据访问记录,统计访问频度较高的热点数据
    • 利用LRU数据删除策略,构建数据留存队列 例如:storm与kafka配合
  • 准备工作:

    • 将统计结果中的数据分类,根据级别,redis优先加载级别较高的热点数据
    • 利用分布式多服务器同时进行数据读取,提速数据加载过程
    • 热点数据主从同时预热
  • 实施:

    • 使用脚本程序固定触发数据预热过程
    • 如果条件允许,使用了CDN(内容分发网络),效果会更好
  • 定时刷新缓存

总结

  • 缓存预热就是系统启动前,提前将相关的缓存数据直接加载到缓存系统。避免在用户请求的时候,先查询数据库,然后再将数据缓存的问题!用户直接查询事先被预热的缓存数据!

2、缓存雪崩

  • 缓存雪崩 是指 缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉。

缓存雪崩造成的后果: 数据库服务器崩溃(1)

  1. 系统平稳运行过程中,忽然数据库连接量激增
  2. 应用服务器无法及时处理请求
  3. 大量408,500错误页面出现
  4. 客户反复刷新页面获取数据
  5. 数据库崩溃
  6. 应用服务器崩溃
  7. 重启应用服务器无效
  8. Redis服务器崩溃
  9. Redis集群崩溃
  10. 重启数据库后再次被瞬间流量放倒

缓存雪崩原因

  • 在一个较短的时间内,缓存中较多的key集中过期

问题分析

  • 短时间范围内
  • 大量key集中过期

解决方案(道)

  1. 更多的页面静态化处理 (模板 + 动态数据)
  2. 构建 多级缓存架构 Nginx缓存+redis缓存+ehcache缓存
  3. 检测MySQL严重耗时业务进行优化 对数据库的瓶颈排查:例如超时查询、耗时较高事务等 --> 可以通过慢日志查询, 找到慢SQL, 然后通过explain执行计划分析慢SQL, 进而优化SQL
  4. 灾难预警机制, 监控redis服务器性能指标
    • CPU占用、CPU使用率
    • 内存容量
    • 查询平均响应时间
    • 线程数
  5. 限流、降级 短时间范围内牺牲一些客户体验,限制一部分请求访问,降低应用服务器压力,待业务低速运转后再逐步放开访问

解决方案(术)

  1. LRU与LFU切换 (Redis的内存淘汰策略)
  2. 数据有效期策略调整 (Redis的删除策略, 默认为 定期删除(随机找重点删一批) + 惰性删除)
    • 根据业务数据有效期进行分类错峰,A类90分钟,B类80分钟,C类70分钟
    • 过期时间使用固定时间+随机值的形式,稀释集中到期的key的数量
  3. 超热数据使用永久key
  4. 加锁 慎用, 效率低

解决方案 (总结)

  • 缓存数据的过期时间设置随机防止同一时间大量数据过期现象发生
  • 一般并发量不是特别多的时候,使用最多的解决方案是加锁排队
  • 给每一个缓存数据增加相应的缓存标记,记录缓存的是否失效,如果缓存标记失效,则更新数据缓存。

总结

  • 缓存雪崩就是瞬间过期数据量太大,导致对数据库服务器造成压力。如能够有效避免过期时间集中,可以有效解决雪崩现象的出现 (约40%),配合其他策略一起使用,并监控服务器的运行数据,根据运行记录做快速调整。

Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案_第11张图片

3、缓存击穿

  • 缓存击穿是指缓存中没有但数据库中有的数据(一般是缓存时间到期),这时由于并发用户特别多,同时读缓存没读到数据,又同时去数据库去取数据,引起数据库压力瞬间增大,造成过大压力。
    • 缓存击穿指并发请求大量查询同一条数据, 造成数据库崩溃;
    • 缓存雪崩是不同数据都过期了(大面积缓存数据过期),很多数据都查不到从而查数据库。

数据库服务器崩溃(2)

  1. 系统平稳运行过程中
  2. 数据库请求某一个数据量 瞬间激增
  3. Redis服务器没有大量key过期, 只是一个热点Key过期, 然后大量请求该Key, 都请求到数据库上, 造成数据库崩溃
  4. Redis内存平稳,无波动
  5. Redis服务器CPU正常

缓存击穿的原因

  1. Redis中 某个key过期,该key访问量巨大
  2. 多个数据请求从服务器直接压到Redis后,均未命中
  3. Redis在短时间内发起了大量对数据库同一数据的访问

问题分析

  • 单个高热数据key过期

解决方案(术)

  • 设置热点数据永远不过期。
    • 预先设定热点数据过期时长(不过期/足够长时间不过期)
      • 以电商为例,每个商家根据店铺等级,指定若干款主打商品,在购物节期间,加大 此类信息key的 过期时长
      • 注意:购物节不仅仅指当天,以及后续若干天,访问峰值呈现逐渐降低的趋势
  • 加分布式锁(互斥锁) – 还可以防止超卖问题
    • 加分布式锁,防止被击穿,但是性能会造成瓶颈, 慎重 !
  • 现场调整热点Key的过期时间
    • 监控访问量,对自然流量激增的数据延长过期时间 或 设置为永久性key
  • 后台刷新数据
    • 启动定时任务,高峰期来临之前,刷新数据有效期,确保数据不过期

总结

  • 缓存击穿就是单个高热数据过期的瞬间, 数据访问量较大,未命中redis后,发起了大量对同一数据的数据库问,导致对数据库服务器造成压力。
  • 应对策略应该在业务数据分析预防方面进行,配合运行监控测试与即时调整策略,毕竟单个key的过期监控难度较高,配合雪崩处理策略即可

4、缓存穿透 (布隆过滤器解决)

  • 缓存穿透 是指缓存和数据库中都没有的数据导致所有的请求都落到数据库上,造成数据库短时间内承受大量请求而崩掉。
  • 我们的数据库中的主键都是从0开始的,即使我们将数据库中的所有数据都放到了缓存中。当有人用id = -1来发生恶意请求时,因为redis中没有这个数据,就会直接访问数据库,这就称谓 缓存穿透

解决办法

  • 接口层增加校验,如用户鉴权校验,id做基础校验,id<=0的直接拦截;
  • 从缓存取不到的数据,在数据库中也没有取到,这时也可以将key-value键值对写为key-null,缓存有效时间可以设置短点,如30秒(设置太长会导致正常情况也没法使用)。这样可以防止攻击用户反复用同一个id暴力攻击
  • 使用 布隆过滤器 ,来判断请求的这个key是否存在

Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案_第12张图片

5、缓存降级

流量剧增, 可能造成响应速度慢, 此时可以通过对一些非核心的缓存服务进行降级 !!

  • 当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。
  • 缓存降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。
  • 在进行降级之前要对系统进行梳理,看看系统是不是可以丢卒保帅;从而梳理出哪些必须誓死保护,哪些可降级;比如可以参考日志级别设置预案:
  • 一般:比如有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级;
  • 警告:有些服务在一段时间内成功率有波动(如在95~100%之间),可以自动降级或人工降级,并发送告警;
  • 错误:比如可用率低于90%,或者数据库连接池被打爆了,或者访问量突然猛增到系统能承受的最大阀值,此时可以根据情况自动降级或者人工降级;
  • 严重错误:比如因为特殊原因数据错误了,此时需要紧急人工降级。

服务降级的目的

  • 为了防止Redis服务故障,导致数据库跟着一起发生雪崩问题。** 因此,**对于不重要的缓存数据,可以采取服务降级策略
    • 例如一个比较常见的做法就是,Redis出现问题,不去数据库查询,而是直接返回默认值给用户 (兜底默认值)

布隆过滤器简介

相关文章: https://mp.weixin.qq.com/s/ksxcd5h-My9BE6sLOlBORw

  • 想要尽量避免缓存穿透,一个办法就是对数据进行预校验,在对Redis数据库进行操作前, 先检查数据是否存在,如果不存在就直接返回
  • 如果我们想要查询一个元素是否存在,要保证查询效率,可以选择HashSet,但是如果有10亿个数据,都用HashSet进行存储,内存肯定是无法容纳的。这时就需要 布隆过滤器

布隆过滤器(英语:Bloom Filter)是1970年由布隆提出的。它实际上是一个很长的二进制向量(bit数组)和一系列哈希函数(hash)。布隆过滤器可以用于检索一个元素是否在一个集合中

因为是基于 位数组 和 hash函数 的,所以它的优点空间效率和查询时间都远远超过一般的算法。但 缺点也很明显,那就是有一定的误识别率和删除困难。但是可以通过增加位数组的大小和增加hash函数个数来降低误识别率(只能降低,没法避免

放入过程

  • 布隆过滤器初始化后,位数组中的值都为0。当一个变量将要放入布隆过滤器时,会通过多个hash函数映射到位数组的各个位上,然后将对应位置为1

查询过程

  • 查询依然是通过多个hash函数映射到位数组的各个位上,如果各个位都为1,说明该元素可能存在,注意是可能存在!!。但是如果通过映射后,位数组对应位上不为1,那么该元素肯定不存在

放入过程图解

比如我们的布隆过滤器位一个8位的位数组,并且有3个hash函数对元素进行计算,映射到数组中的各个位上

Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案_第13张图片

我们将字符串”Nyima”放入布隆过滤器中

Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案_第14张图片

接下来将字符串”Cpower”放入布隆过滤器中

Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案_第15张图片

查询过程图解

比如我们要查询字符串”Cpower”是否存在,通过3个hash函数映射到了位数组的三个位置上, 三个位置都为1,那么该字符串可能存在

Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案_第16张图片

比如我们要查询字符串”SWPU”是否存在,通过3个hash函数映射到了位数组的三个位置,发现有一个位置不为1,那么该字符串肯定不存在

Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案_第17张图片

比如我们要查询字符串”Hulu”是否存在,通过3个hash函数映射到了位数组的三个位置,发现所有位置都为1,但是我们前面并没有将字符串”Hulu”放入布隆过滤器中,所以这里发生了误判

Redis——Redis集群原理、缓存预热、缓存击穿、缓存穿透、缓存雪崩的解决方案_第18张图片

增加位数组的大小和hash函数个数可以降低误判率,但是无法避免误判

你可能感兴趣的:(#,Redis,Redis,Redis集群,cluster,集群原理)