干货!教你深入理解缓存问题,使用缓存无压力!

栏目: 数据库 · 发布时间: 5年前

内容简介:在高并发或大数据的场景下,面对热点数据的使用性能问题,缓存是常用的解决方式,主要作用包括将数据写入速度更快的存储设备;将数据缓存到离应用最近的位置;将数据缓存到离用户最近的位置等。缓存雪崩可简单理解为,由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库,对数据库CPU和内存造成巨大压力,严重的会导致数据库宕机,从而形成一系列连锁反应,造成整个系统崩溃。

在高并发或大数据的场景下,面对热点数据的使用性能问题,缓存是常用的解决方式,主要作用包括将数据写入速度更快的存储设备;将数据缓存到离应用最近的位置;将数据缓存到离用户最近的位置等。

干货!教你深入理解缓存问题,使用缓存无压力!

一、缓存雪崩

缓存雪崩可简单理解为,由于原有缓存失效,新缓存未到期间(例如:我们设置缓存时采用了相同的过期时间,在同一时刻出现大面积的缓存过期),所有原本应该访问缓存的请求都去查询数据库,对数据库CPU和内存造成巨大压力,严重的会导致数据库宕机,从而形成一系列连锁反应,造成整个系统崩溃。

缓存失效时的雪崩效应对底层系统的冲击很大,大多系统设计者采用加锁或队列的方式来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量并发请求落到底层存储系统上。另外一个简单方案就是分散缓存失效时间,例如可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存过期时间的重复率就会降低,很难引发集体失效的事件。

1.若一般并发量不是特别多,常用解决方案是加锁排队,可减轻数据库的压力,但不会提高系统吞吐量。假设在高并发下,缓存重建期间key是锁着的,此时1000个请求中999个在阻塞状态,同样会导致用户等待超时,这种方法治标不治本!

注意:使用加锁排队的方式解决分布式环境的并发问题,可能还要解决分布式锁的问题;线程还会被阻塞,用户体验较差,因此,在真正的高并发场景下很少使用!

2.另一个解决方案是,给每一个缓存数据增加相应的缓存标记,记录缓存是否失效,如果缓存标记失效,则更新数据缓存。

解释说明

1.缓存标记:记录缓存数据是否过期,若过期会触发通知另外的线程,则在后台更新实际key的缓存;

2.缓存数据:它的过期时间比缓存标记的时间延长1倍,例:标记缓存时间30分钟,数据缓存设置为60分钟。 这样,当缓存标记key过期后,实际缓存还能将旧数据返回给调用端,直到另外的线程在后台更新完成后,才会返回新缓存。

关于缓存崩溃的三种解决方案:使用锁或队列、设置过期标志更新缓存、为key设置不同的缓存失效时间,还有一种被称为“二级缓存”的解决方法,有兴趣的小伙伴可自行研究。

二、缓存穿透

缓存穿透是指用户无法在缓存中查询数据,需要去数据库查询,再返回空(相当于进行两次无用查询)。此时请求就绕过缓存直接查数据库,这就是经常提到的缓存命中率问题。

有多种方法可有效的解决缓存穿透问题,最常见的是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一定不存在的数据则会被bitmap拦截掉,从而避免对底层存储系统的查询压力。

另外更为简单的方法是,若一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然将此空结果进行缓存,过期时间会很短,最长不超过五分钟。通过这个直接设置的默认值存放到缓存,这样第二次到缓冲中获取就有值了,而不会继续访问数据库,这种办法最为简单。

将空结果进行缓存,下次同样的请求则直接返回空,即可避免当查询的值为空时引起的缓存穿透。同时也可单独设置一个缓存区域存储空值,对要查询的key进行预先校验,然后再放行给后面的正常缓存处理逻辑。

三、缓存预热

缓存预热就是系统上线后,将相关的缓存数据直接加载到缓存系统中。这样即可避免在用户请求时,先查询数据库,再将数据缓存的问题,用户可直接查询事先被预热的缓存数据。

解决思路:

1.直接写一个缓存刷新页面,上线时手工操作;

2.数据量不大时,可以在项目启动时自动进行加载;

3.定时刷新缓存。

四、缓存更新

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

1.定期清理过期缓存;

2.当有用户请求时,判断缓存是否过期,过期则在底层系统得到新数据并更新缓存。

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

五、缓存降级

当访问量剧增、服务出现问题(如响应时间慢或不响应)或非核心服务影响到核心流程的性能时,仍需保证服务可用,即使是有损服务。系统可以根据一些关键数据进行自动降级,也可配置开关实现人工降级。

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

在进行降级之前要对系统进行梳理,确认哪些需要保护,哪些可降级;比如可参考日志级别设置预案:

1.一般:有些服务偶尔因网络抖动或者服务正在上线而超时,可自动降级;

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

3.错误:可用率低于90%,或数据库连接池被耗尽,或访问量猛增到系统能承受的最大阀值,此时可根据情况自动降级或者人工降级;

4.严重错误:因为特殊原因数据错误,此时需要紧急人工降级。


以上所述就是小编给大家介绍的《干货!教你深入理解缓存问题,使用缓存无压力!》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Java Web编程从入门到实践

Java Web编程从入门到实践

徐林林 / 清华大学出版社 / 2010-3 / 59.80元

《Java Web编程从入门到实践》内容简介:Java Web开发是目前最流行的网络开发技术之一。《Java Web编程从入门到实践》由浅入深,结合大量的实例系统地讲解了关于Java Web开发方面的知识。全书内容包括Java Web开发的基础知识、Java Web开发环境的搭建、JSP技术详解、Servlet技术详解、JSP+Servlet+JavaBean开发模式、JDBC接口的使用方法、Hi......一起来看看 《Java Web编程从入门到实践》 这本书的介绍吧!

SHA 加密
SHA 加密

SHA 加密工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具