专栏首页烟草的香味缓存在高并发场景下的常见问题

缓存在高并发场景下的常见问题

缓存一致性问题

当数据时效性要求很高时,需要保证缓存中的数据与数据库中的保持一致,而且需要保证缓存节点和副本中的数据也保持一致,不能出现差异现象。这就比较依赖缓存的过期和更新策略。一般会在数据发生更改的时,主动更新缓存中的数据或者移除对应的缓存。

缓存并发问题

缓存并发问题通常发生在高并发的场景下, 当一个缓存key过期时,有大量的请求在获取该缓存key, 多个请求同时发现缓存过期, 因此多个请求会同时访问数据库来查询最新数据, 并且回写缓存, 这样会造成应用和数据库的负载增加, 性能降低, 由于并发较高, 甚至可能导致数据库被压死.

那么如何解决这个问题呢?

  1. 本地锁. 与分布式锁类似,我们通过本地锁的方式来限制只有一个线程去数据库中查询数据,而其他线程只需等待,等前面的线程查询到数据后再访问缓存。但是,这种方法只能限制一个服务节点只有一个线程去数据库中查询,如果一个服务有多个节点,则还会有多个数据库查询操作,也就是说在节点数量较多的情况下并没有完全解决缓存并发的问题
  2. 分布式锁. 使用分布式锁,保证对于每个key同时只有一个线程去查询后端服务,其他线程没有获得分布式锁的权限,因此只需要等待即可。这种方式将高并发的压力转移到了分布式锁,因此对分布式锁的考验很大
  3. 软过期. 软过期指对缓存中的数据设置失效时间,就是不使用缓存服务提供的过期时间,而是业务层在数据中存储过期时间信息,由业务程序判断是否过期并更新,在发现了数据即将过期时,将缓存的时效延长,程序可以派遣一个线程去数据库中获取最新的数据,其他线程这时看到延长了的过期时间,就会继续使用旧数据,等派遣的线程获取最新数据后再更新缓存。也可以通过异步更新服务来更新设置软过期的缓存,这样应用层就不用关心缓存并发的问题了。

缓存穿透问题

在高并发场景下,如果某一个key被高并发访问,没有被命中,出于对容错性考虑,会尝试去从后端数据库中获取,从而导致了大量请求达到数据库,而当该key对应的数据本身就是空的情况下,这就导致数据库中并发的去执行了很多不必要的查询操作,从而导致巨大冲击和压力。

缓存穿透通常是由恶意攻击或者无意造成的

缓存穿透的解决办法:

1.缓存空对象

对查询结果为空的对象也进行缓存,如果是集合,可以缓存一个空的集合(非null),如果是缓存单个对象,可以通过字段标识来区分。这样避免请求穿透到后端数据库。同时,也需要保证缓存数据的时效性。

2.单独过滤处理

我们通常将空值缓存起来,再次接收到同样的查询请求时,若命中缓存并且值为空,就会直接返回,不会透传到数据库,避免缓存穿透。当然,有时恶意袭击者可以猜到我们使用了这种方案,每次都会使用不同的参数来查询,这就需要我们对输入的参数进行过滤,例如,如果我们使用ID进行查询,则可以对ID的格式进行分析,如果不符合产生ID的规则,就直接拒绝,或者在ID上放入时间信息,根据时间信息判断ID是否合法,或者是否是我们曾经生成的ID,这样可以拦截一定的无效请求。

缓存雪崩问题

缓存雪崩指缓存服务器重启或者大量缓存集中在某一个时间段内失效,给后端数据库造成瞬时的负载升高的压力,甚至压垮数据库的情况。

缓存雪崩是由缓存同时失效造成的

通常的解决办法是对不同的数据使用不同的失效时间,甚至对相同的数据、不同的请求使用不同的失效时间. 比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。

缓存击穿问题

对于一些设置了过期时间的key,如果这些key可能会在某些时间点被超高并发地访问,是一种非常“热点”的数据。这个时候,需要考虑一个问题:缓存被“击穿”的问题,这个和缓存雪崩的区别在于这里针对某一key缓存,前者则是很多key。

这个问题的解决办法,网上的一些我也没看太懂,实在不好意思了

本文分享自微信公众号 - 烟草的香味(hujing-bc),作者:胡靖哥哥

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-10-26

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Python导入运行的当前模块报错

    众所周知,Python模块导入的查找路径可以通过sys.path查看,我看了一下:

    烟草的香味
  • Java8 Lambda表达式

    在Python中是有的。但是Python中万物皆对象,直接将函数赋值给一个变量即可,那么在Java中该如何使用lambda表达式呢?

    烟草的香味
  • Trie树

    他会自动显示相关的搜索,不知道有没有想过这个功能是如何实现的呢?面对海量的数据,它怎么能在我输入的同时,如此快速的检索到相关内容呢?当我查找资料后,就遇到了它,...

    烟草的香味
  • 后端服务慢成狗?试试这 7 招!

    优化代码实现是第一位的,特别是一些不合理的复杂实现。如果结合需求能从代码实现的角度,使用更高效的算法或方案实现,进而解决问题,那是最简单有效的。

    Java技术栈
  • 一文彻底读懂优秀开源产品MyBatis一级缓存设计!

    缓存是 MyBatis 中非常重要的特性。合理使用缓存能够减少数据库 IO,显著提升系统性能。但是在分布式环境下,如果使用不当,则可能会带来数据一致性问题。My...

    孙玄@奈学教育
  • 干货|这可能是最全的高并发、高性能、高可用解决方案总结

    在计算机中,缓存是存储数据的硬件或软件组件,以便可以更快地满足将来对该数据的请求。存储在缓存中的数据可能是之前计算结果,也可能是存储在其他位置的数据副本。

    崔庆才
  • Redis 缓存设计原则

    本文为作者原创,版权归作者雪飞鸿所有。 转载必须保留文章的完整性,且在页面明显位置处标明原文链接。

    雪飞鸿
  • 经常用Redis,这些坑你知道吗?

    作者简介:曾任职于阿里巴巴,每日优鲜等互联网公司,任技术总监,15年电商互联网经历。

    用户7927337
  • 使用Redis和Java进行数据库缓存

    您在数据库中获得的信息越多,随着时间的推移它就越慢。即使是为支持许多并发请求而精心设计的数据库管理系统也将最终达到极限。

    银河1号
  • 缓存穿透、并发和雪崩那些事 转

    作者:李艳鹏,阿里资深技术专家!著有《可伸缩服务架构》,《分布式服务架构》等作品,在区块链,聚合支付,电商等领域有一定的积累!

    wuweixiang

扫码关注云+社区

领取腾讯云代金券