• Redis系列(八)--缓存穿透、雪崩、更新策略


    1、缓存更新策略

      1、LRU/LFU/FIFO算法剔除:例如maxmemory-policy

      2、超时剔除,过期时间expire,对于一些用户可以容忍延时更新的数据,例如文章简介内容改了几个字

      3、主动更新:代码控制生命周期,对于一些必须实时更新的数据,例如金额

    策略 一致性 维护成本
    LRU/LFU/FIFO算法剔除 最差
    超时剔除 较差
    主动更新

    2、缓存粒度问题

      1、通用性:全量属性最好

      2、占用空间:部分属性最好

      3、代码维护:表面上看全量属性最好

    大部分应用来说都是缓存部分属性

    3、缓存穿透

      指查询一个一定不存在的数据,由于缓存是不命中时,出于容错考虑,如果从存储层查不到数据则不写入缓存,这将导致这个不存在的数据每次

    请求都要到存储层去查询,失去了缓存的意义。在流量大时,可能DB就挂掉了,要是有人利用不存在的key频繁攻击我们的应用,这就是漏洞。

    优化到极致的单机mysql的数据库连接为300-700之间,300为机械硬盘数据,700为固态硬盘数据

    原因:

      1、业务代码有问题,直接返回了,没有写cache层

      2、恶意攻击、爬虫等

    如何发现:

      1、业务的响应时间,通过监控系统

      2、业务本身的问题

      3、相关指标:总调用数、缓存层命中数、存储层命中数

    解决方法:

      处理缓存穿透的方法有很多,其实无外乎就是对数据进行过滤筛选,把真正有效的数据进行访问,无效数据直接过滤掉。

    1、缓存空对象

      设置过期时间,过期时间会很短,最长不超过五分钟,用来减少storage压力,这样需要更多的键,缓存和存储层短期数据不一致

    2、布隆过滤器拦截

      将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。

    3、对所有可能查询的参数以hash形式存储,在控制层先进行校验,不符合则丢弃

    4、缓存雪崩

    缓存集中在一段时间内失效,新的缓存未到,或者Redis缓存宕机,发生大量的缓存穿透,所有的查询都落在数据库上,造成了缓存雪崩

    优化方案:

      1、保证缓存高可用性。master-slave、sentinel、cluster

      2、依赖隔离组件(线程池/信号量组件)为后端限流,例如Hystrix,还有本地encache缓存

      3、提前演练

      4、Redis持久化,快速恢复缓存数据

    解决办法:

      1、在缓存失效后,通过加锁或者队列来控制读数据库写缓存的线程数量。比如对某个key只允许一个线程查询数据和写缓存,其他线程等待。

      2、可以通过缓存reload机制,预先去更新缓存,再即将发生大并发访问前手动触发加载缓存 不同的key,设置不同的过期时间,让缓存失效

    的时间点尽量均匀做二级缓存,或者双缓存策略。A1为原始缓存,A2为拷贝缓存,A1失效时,可以访问A2,A1缓存失效时间设置为短期,A2设置

    为长期。

    5、缓存预热

      缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统。这样避免,用户请求的时候,再去加载相关的数据。

    解决思路:
      1、直接写个缓存刷新页面,上线时手工操作下。

      2、数据量不大,可以在WEB系统启动的时候加载。

      3、定时刷新缓存。

    6、缓存过期策略

      除了缓存服务器自带的缓存失效策略之外(Redis默认的有6中策略可供选择),我们还可以根据具体的业务需求进行自定义的缓存淘汰,常见的

    策略有两种:

      (1)定时删除

      Redis将每个设置过期时间的key放到一个独立的字典中,以后定期遍历字典删除过期的key

      Redis默认100ms进行一次过期扫描,不会扫描字典中所有的key,而是采用贪心算法。从字典中随机20个key,删除20个key里面过期的key,如果

    过期的key的比率超过1/4就重复之前的步骤

      (2)惰性删除

      当有用户请求过来时,再判断这个请求所用到的缓存是否过期,过期的话就去底层系统得到新数据并更新缓存

    对比:

      两者各有优劣,第一种的缺点是维护大量缓存的key是比较麻烦的,第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂

    可以采用定期删除+惰性删除两种策略

    7、内存淘汰策略

    Redis的数据都是放在内存中的,如果Redis能使用10G内存,但是数据却有20G,这时候就需要干掉10G数据,去掉不常用的数据,保留常用的数据

    Redis提供的内存淘汰策略有如下几种:

      1、no-eviction 不会继续服务写请求 (DEL 请求可以继续服务),读请求可以继续进行。这样可以保证不会丢失数据,但是会让线上的业务不能

    持续进行。这是默认的淘汰策略。

      2、volatile-lru 尝试淘汰设置了过期时间的 key,最少使用的 key 优先被淘汰。没有设置过期时间的 key 不会被淘汰,这样可以保证需要持

    久化的数据不会突然丢失。(这个是使用最多的)

      3、volatile-ttl 跟上面一样,除了淘汰的策略不是 LRU,而是 key 的剩余寿命 ttl 的值,ttl 越小越优先被淘汰。

      4、volatile-random 跟上面一样,不过淘汰的 key 是过期 key 集合中随机的 key。

      5、allkeys-lru 区别于 volatile-lru,这个策略要淘汰的 key 对象是全体的 key 集合,而不只是过期的 key 集合。这意味着没有设置过期

    时间的 key 也会被淘汰。

      6、allkeys-random 跟上面一样,不过淘汰的策略是随机的 key。allkeys-random 跟上面一样,不过淘汰的策略是随机的 key。

    lru策略可以保证Redis中的数据都是近期使用频率比较高的数据,也就是热点数据

    策略使用规则:

      1、如果数据访问分布差别很大,就是用allkeys-lru

      2、如果数据访问分布均匀,访问频率差不多,使用allkeys-random  

    7、缓存降级

      当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍然需要保证服务还是可用的,即使是有损

    服务。系统可以根据一些关键数据进行自动降级,也可以配置开关实现人工降级。

      降级的最终目的是保证核心服务可用,即使是有损的。而且有些服务是无法降级的(如加入购物车、结算)。

    在进行降级之前要对系统进行梳理,看看系统是不是可以丢卒保帅;从而梳理出哪些必须誓死保护,哪些可降级;

    比如可以参考日志级别设置预案:

      (1)一般:比如有些服务偶尔因为网络抖动或者服务正在上线而超时,可以自动降级

      (2)警告:有些服务在一段时间内成功率有波动(如在95~100%之间),可以自动降级或人工降级,并发送告警

      (3)错误:比如可用率低于90%,或者数据库连接池被打爆了,或者访问量突然猛增到系统能承受的最大阀值,此时可以根据情况自动降级或

    者人工降级

      (4)严重错误:比如因为特殊原因数据错误了,此时需要紧急人工降级

    8、无底洞问题

      由Facebook产生的,有3000个memcache节点,性能却下降了,例如mget、mset等时间复杂度从O(1)到O(Node)

    优化:

      1、优化命令:keys、hgetall、bigkey

      2、减少网络通信时间

      3、降低接入成本:例如客户端长连接、连接池、NIO等

      4、热点key重建优化:高并发情况下,可能出现很多线程重建缓存的情况

    热点key+较长的重建时间

    1、三个目标:

      减少重缓存的次数

      数据尽可能一致

      减少潜在危险

    2、两个解决

      互斥锁(mutext key)

      setex、setnx能够保证原子性

    永远不过期:给每个value设置逻辑过期时间

  • 相关阅读:
    [BZOJ3160]万径人踪灭
    [BZOJ5212][ZJOI2018]历史
    [BZOJ3563&3569]DZY Loves Chinese
    [HDU4336]Card Collector
    [HDU4652]Dice
    [POJ3683]Priest John's Busiest Day
    ISODateTimeFormat 转换2019-08-15T00:36:49.366456463Z 日期格式
    GoTTY-K8S-Docker 终端
    【php】PHP对redis操作详解
    【tool】VLC播放rtmp协议
  • 原文地址:https://www.cnblogs.com/huigelaile/p/10900647.html
Copyright © 2020-2023  润新知