Redis企业级解决方案

目录

缓存预热

问题排查

解决方案

总结

缓存雪崩

解决方案

​缓存击穿

常见的解决方案

对比

缓存穿透

解决方案


缓存预热

新的缓存系统中没有任何数据,在缓存重建的过程中,系统性能和负载都不太好,所以最好是再系统上线之前把要缓存的热点数据加载到缓存中,这种缓存手段就是缓存预热。如果不预热会有如下问题产生: Redis服务器启动后会迅速宕机,数据库和应用服务也可能会随之宕机。

问题排查

  1. 请求数量较高;
  2. 主从之间数据吞吐量较大,数据同步操作频度较高,因为刚刚启动时,缓存中没有任何数据;

解决方案

准备工作:

  1. 日常例行统计数据访问记录,统计出访问频度较高的热点数据;
  2. 将统计结果中的数据分类,根据级别, Redis优先加载级别较高的热点数据。

实施: 

  1. 使用脚本程序固定触发数据预热过程(使用Linux搭服务器编写shell脚本);
  2. 条件允许的话使用CDN(内容分发网络),效果会更好。 

CDN(Content Delivery Network)内容分发网络。基本思路是尽可能避开互联网上有可能影响数据传输速度和稳定性的瓶颈和环节,使内容传输得更快更稳定。通过在网络各处放置节点服务器所构成的在现有的互联网基础上的一层智能虚拟网络,CDN系统能够及时的根据网络流量和各节点的连接、负载状况以及到用户的距离和响应时间等综合信息将用户的请求重新导向离用户最近的服务节点上。其目的是使用户可就近取得所需内容,解决网络拥挤的状况,提高用户访问网站的响应速度。

总结

  1. 缓存预热就是系统启动前,提前将相关的缓存热点数据直接加载到缓存系统中。
  2. 避免服务器在刚启动的时候遇到大量请求的冲击所导致宕机。
  3. 可以让用户在服务器刚启动时就可以直接在缓存系统中查询事先被预热的缓存数据。

缓存雪崩

缓存雪崩是指在同一时间大量的缓存key同时失效或者Redis服务宕机,导致大量请求到达数据库,给数据库带来巨大压力。 

解决方案

  • 调整删除策略: LRU和LFU的删除策略,按照命中次数去进行删除,保留高热数据key,超热数据使用永久的key;
  • 稀释数据有效期: 给不同的key的TTL设置随机值;
  • 定期维护: 对即将过期的热点数据进行延时策略,延长其过期时间;
  • 利用Redis集群提高服务的可用性,这样当某一个Redis系统出现问题时,可以通过集群中的其他Redis服务来顶替;
  • 给缓存业务添加降级限流策略;
  • 给业务添加多级缓存;

缓存击穿

缓存击穿是指: 一个被高并发访问并且缓存重建业务较复杂的热点key突然过期,这个期间持续的高并发访问量就会穿破Redis缓存而直接到达数据库,会在瞬间给数据库带来巨大的冲击,导致数据库扛不住压力而集中宕机。

逻辑分析:  假设线程1在查询缓存之后,本来应该去查询数据库,并把这个数据重新加载到缓存,此时只要线程1完整走完这个流程,其他线程也就可以在缓存中正常访问这个数据了。但是假设在线程1走完之前,后续的线程 2,3,4 同时过来访问这个数据,此时它们都不能从缓存中查询到想要访问的数据,那么这些请求就会同时涌入数据库,同时执行数据库代码,对数据库造成巨大的压力,从而导致数据库宕机。

常见的解决方案

  • 互斥锁;
  • 逻辑过期;

互斥锁: 利用互斥性。假设线程请求进入数据库,只能一个一个的访问,从而避免对于数据库的压力过大,但这也会影响查询性能,因为此时会让多个线程串行执行,我们可以采用 tryLock方法 + double check来解决这样的问题。

逻辑分析: 假设现在线程1过来访问,他查询缓存没有命中,但是此时他获得到了锁的资源,那么线程1就会一个人去执行逻辑,假设现在线程2过来,线程2在执行过程中,并没有获得到锁,那么线程2就可以进行到休眠,直到线程1把锁释放后,线程2获得到锁,然后再来执行逻辑,此时就能够从缓存中拿到数据了。

逻辑过期方案 

逻辑分析: 之所以会出现缓存击穿的问题,主要原因是因为我们对key设置了过期时间,假设我们不设置过期时间,其实就不会出现这样的问题,但是如果不设置过期时间,数据就会一直占用内存,那么我们可以使用逻辑过期方案。

  1. 我们把过期时间设置在Redis的value中,注意: 这个过期时间并不会直接作用于Redis,而是我们后续通过逻辑去处理。
  2. 假设线程1去查询缓存,然后从value中判断出来当前的数据已经过期了,此时线程1会获得互斥锁,那么其他线程会进行阻塞,获得了锁的线程会开启一个线程2去进行以前的重构数据的逻辑,直到新开的线程执行完逻辑后才会释放锁,而线程1本身直接进行返回旧数据。
  3. 假设线程3现在过来访问数据,它也直接返回旧数据,只有等到线程2把重建数据构建完后,其他的线程才会访问到正确的新数据。

这种方案的巧妙之处在于,异步构建缓存,缺点在于在重建完成之前,访问到的都是脏数据。

对比

互斥锁方案: 由于保证了互斥性,所以数据会同步,且实现简单,因为只需要一把锁而已,没有其他的事需要考虑,所以也没有额外的内存消耗,缺点就是所有的请求都会由并行变为串行,性能上会打折扣,同时也有可能会出现死锁的问题。

逻辑过期方案: 线程请求过程中不需要等待,性能好,有一个异步线程会持有锁去进行重构数据,但是在重构完成之前,一直读到的都是脏数据,且实现麻烦。

缓存穿透

是指客户端请求的数据在缓存中和数据库中都不存在,这样缓存永远不会失效,大量请求会进入数据库。

解决方案

1. 缓存空对象

  • 优点: 实现简单,维护方便;
  • 缺点: 额外的内存消耗,可能会造成短期的不一致;
  • 思路分析: 哪怕数据库中不存在这个数据,我们也向Redis中存入一个空值,这样下次来访问这个不存在数据,也能在Redis中找到这个数据,就不会进入到数据库中。

2. 布隆过滤

  • 优点: 内存占用少,没有多余的key;
  • 缺点: 实现复杂,存在误判可能;
  • 思路分析: 布隆过滤器其实采用的是哈希思想来解决这个问题,通过一个庞大的二进制数组,走哈希思想去判断当前这个要查询的数据是否存在,如果布隆过滤器判断存在,则放行,让这个请求去访问Redis,哪怕此时redis中的数据过期了,但是数据库中一定存在这个数据,在数据库中查询出来这个数据后,再将其放入到redis中;如果布隆过滤器判断不存在,则直接返拒绝请求。
  • 这种方式优点在于节约内存空间,但存在误判,原因在于: 布隆过滤器走的是哈希思想,不可避免地存在哈希冲突。

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值