zoukankan      html  css  js  c++  java
  • 应用缓存的常见问题及解决

    使用缓存一些常见的套路问题。

     

    缓存穿透

    • 场景:大量请求访问某个不存在的KEY

    在缓存设计中,查询缓存 -> key不存在 -> 回源DB -> 更新缓存,这是一个典型的方案。

    缓存穿透是指查询一个一定不存在的Key,由于缓存层不存在,将导致这个不存在的数据每次请求都要到存储层去查询,直接对DB造成影响。在恶意攻击和失败回调中可能会出现这种情况。

    • 解决方案

    1.对空对象进行缓存。对查询结果为空的情况也进行缓存,如当此查询结果为空,设置Key对应对象为NULL,缓存时间设置短一点,存储层中有数据后及时更新。

    2.对所有可能查询的参数Key以hash形式存储,在控制层先进行校验,不符合则丢弃。最常见的是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。比较适合命中不高,但是更新不频繁的数据。

     

    缓存失效

    • 场景:缓存中大量的Key集中在一段时间内失效,数据库的压力凸显
    • 解决方案

    1.可以分析用户行为,尽量让失效时间点均匀分布。针对失效时间相同的key,在设置失效时间时不设置固定的时间,而在原有基础上加上一个随机的值,比如1分钟-5分钟,这样就可以有效分散开缓存失效的时间。

    2.考虑用加锁或者队列的方式保证缓存的单线程(进程)写,从而避免失效时大量的并发请求落到底层存储系统上。

     

    缓存并发

    • 场景:在高并发场景下,某些业务有可能多个请求并发的去从数据库获取数据

    有时候如果网站并发访问高,一个缓存如果失效,可能出现多个进程同时查询DB,同时设置缓存的情况,如果并发确实很大,这也可能造成DB压力过大。

    • 解决方案

    1.添加分布式锁,在缓存更新或者过期的情况下,先尝试获取到锁,当更新或者从数据库获取完成后再释放锁,其他的请求只需要牺牲一定的等待时间,即可直接从缓存中继续获取数据。

    2.定期从DB里查询数据,再刷到缓存里面,确保缓存里面的数据一直可以读到。

     

    缓存雪崩

    • 场景:当发生大量的缓存穿透,例如缓存挂掉,或者对某个失效的缓存的大并发访问

    由于缓存扛了大量的请求,有效保护了数据库的安全。但是当缓存雪崩,所用请求就会瞬间全部打到DB上,可能会导致数据库崩溃。

    • 解决方案

    1.保证缓存服务的高可用性,当一个实例挂掉的时候,请求也可以转移到集群的其他实例上。缓存失效时的雪崩效应对底层系统的冲击非常大,这时候可以使用双缓存机制,在工作缓存之外另外维护一层灾备缓存。

    2.使用降级策略,当缓存服务出现问题时,可以暂时对用户展示一份固定的数据,避免系统的崩溃,等待缓存服务的恢复。前端也应该有此机制,比如当后端接口返回非正常数据时,将之前保存的旧数据固定展示给用户,避免页面崩溃的问题。

     

    缓存数据的淘汰

     

    缓存淘汰的策略有两种:

    1.定时去清理过期的缓存

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

    两者各有优劣,第一种的缺点是维护大量缓存的key是比较麻烦的,第二种的缺点就是每次用户请求过来都要判断缓存失效,逻辑相对比较复杂,具体用哪种方案,根据自己的应用场景来权衡。

     

    更新缓存还是淘汰缓存

     

    什么是更新缓存:数据不但写入数据库,还会写入缓存

    什么是淘汰缓存:数据只会写入数据库,不会写入缓存,只会把数据淘汰掉

    更新缓存的优点:缓存不会增加一次miss,命中率高

    淘汰缓存的优点:简单

     

    先操作数据库还是先操作缓存

     

     

    假设先写数据库,再淘汰缓存:第一步写数据库操作成功,第二步淘汰缓存失败,则会出现DB中是新数据,Cache中是旧数据,数据不一致。

    假设先淘汰缓存,再写数据库:第一步淘汰缓存成功,第二步写数据库失败,则只会引发一次Cache miss。

    所以结论是:先淘汰缓存,再写数据库

     

    参考:

    缓存与数据库一致性保证

    缓存更新的套路

  • 相关阅读:
    实现三栏布局
    Element对象
    React中组件间通信的方式
    CSS实现展开动画
    Vue中组件间通信的方式
    java面试一日一题:mysql执行delete数据真的被删除了吗
    java面试一日一题:讲对mysql的MVCC的理解
    java面试一日一题:讲下mysql中的锁
    java面试一日一题:如何优化sql
    java面试一日一题:在创建微服务时,是用RPC还是http
  • 原文地址:https://www.cnblogs.com/binyue/p/8057890.html
Copyright © 2011-2022 走看看