| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> 大数据 -> 【Java进阶营】Redis技术专题之缓存击穿、缓存雪崩、缓存穿透 -> 正文阅读 |
|
[大数据]【Java进阶营】Redis技术专题之缓存击穿、缓存雪崩、缓存穿透 |
当我们使用一项技术时,我们就需要对它有一定的了解,知道我们为什么要去使用它,能够分析使用这项技术所带来的的回报以及我们所需要付出的代价。 缓存所带来的收益: **?高速读写:缓存会加速读写速度,利用CPU L1/L2/L3 Cache、Linux page Cache加速硬盘读写、浏览器缓存、Ehcache缓存缓存数据,其性能都会比关系型数据库高很多,内存级别的读写性能大大优于磁盘级别的读写性能。** **? ? ? ?降低后端负载:后端服务器业务通过使用Redis减少对MySQL的请求访问,降低MySQL负载等。** 缓存所带来的代价: **? ? ? ?数据不一致:缓存层和数据库层面数据不一致,例如Redis已经对某条复杂的数据进行缓存,此时通过后台修改该数据,由于大部分情况下我们不会主动对Redis进行数据删除,因为从性能以及包容性来说都不需要进行删除操作,所以就导致缓存数据同步不及时,这些都和我们自身应用更新策略有关,需要根据实际情况合理设置数据缓存过期时间等相关操作。** 代码维护成本(人工成本):不适用Redis缓存的情况下,我们只需读写MySQL就能实现功能,但当我们加入缓存之后就需要去维护缓存数据的处理逻辑,增加了代码复杂度。某些情况下会降低项目开发以及测试效率,例如测试人员需要测试有缓存时的情况,也要测试没有缓存时的情况,另外当测试人员测试功能无需关注缓存时需手动清除对应缓存,否则需要等待数据缓存过期,延长测试时间。 性能风险:堆内缓存由于是存储在本地服务器中,由JVM或者本地服务器来维护数据,可能带来内存溢出的风险甚至影响用户进程,如ehCache、loadingCache。 堆内缓存和远程服务器缓存如何选择?对于这个问题主要考虑以下几点: 堆内缓存一般性能更好,远程缓存需要套接字传输。 **????????用户级别缓存尽量采用远程缓存(例如集群架构下,多台机器会重复缓存同一组数据)。** **????????大数据量尽量采用远程缓存,避免造成应用服务器压力过大,遵循服务节点化原则。** [2.缓存穿透] [2.1 什么是缓存穿透?] 上面这张图是我们正常业务场景下的一个流程(客户端->服务端[Redis->DB]),那么缓存穿透指的是当用户查询数据,再缓存中不存在,并且在数据库也不存在时,导致用户查询这样的数据(或者恶意攻击) 在缓存中找不到对应key的value,每次都需要要在数据库中查询一遍,然后返回空值。其实这就相当于进行了两次无用的查询,这样请求就绕过缓存直接查数据库,对数据库造成了很大的压力。在此我向大家推荐一个架构学习交流圈。交流学习指导伪鑫:1253431195(里面有大量的面试题及答案)里面会分享一些资深架构师录制的视频录像:有Spring,MyBatis,Netty源码分析,高并发、高性能、分布式、微服务架构的原理,JVM性能优化、分布式架构等这些成为架构师必备的知识体系。还能领取免费的学习资源,目前受益良多 [2.2 如何防止缓存穿透?] 缓存空值:如果DB查询返回数据或者业务结果为空,此时我们仍然将空结果进行缓存,设置较短的过期时间(不超过五分钟)。 **? ? ? ?采用布隆过滤器BloomFilter:事先将所有可能存在的数据哈希后放入到一个足够大的BitMap中,若一个数据一定不存在则会被拦截掉,从而避免了对底层存储系统的查询压力。关于布隆过滤器后面会写一篇博客对其进行详细介绍。** [3.缓存雪崩] [3.1 什么是缓存雪崩?] **?? ?如果缓存集中在一段时间内失效,发生大量的缓存穿透,所有查询都落在数据库上,就会造成了缓存雪崩。 由于原有缓存失效,新缓存未到期间所有原本应该访问缓存的请求都需要去查询数据库,从而对数据库服务CPU和内存造成巨大压力,严重可能会造成数据库服务宕机。** [3.2 如何防止缓存雪崩?] 这里我们看看如何防止缓存雪崩: **? ? ? 加锁排队:维护一个mutex互斥锁,通过Redis的SETNX命令去设置一把当前业务操作的锁(例如setnx lock_uid_001 value nullValue、setnx lock_white_list value nullValue),当操作成功时,再进行LoadDB操作回设缓存,否则重试get缓存。** 数据预热:缓存预热就是当我们新部署一个项目系统时,将相关缓存数据直接加载到缓存中。这样可以避免在用户请求时候,再去查询数据库放入缓存。用户可以直接查询事先被预热的缓存数据,可以预热大并发量、热度高的Key缓存数据。 **? ? ? ?双层缓存策略:同一条数据我们可以维护两套缓存,C1为原始缓存,C2为拷贝缓存,当C1失效时,可以读取C2,都不存在时再去访问数据库回设,当然C1缓存失效时间需要设置为短期,而C2设置为长期。这种方式最大缺点就是占用的内存翻倍。** **? ? ? ?定时更新缓存策略:对于失效性要求低的缓存,可以在容器启动初始化时加载放入缓存,采用定时任务更新或移除缓存。** **? ? ? ?时间浮动策略:设置不同过期时间,让缓存失效的时间点尽量均匀,避免集中失效** [穿透] **?穿透:频繁查询一个不存在的数据,由于缓存不命中,每次都要查询持久层。从而失去缓存的意义。** 解决办法: **? ? 1.用一个bitmap和n个hash函数做布隆过滤器过滤没有在缓存的键。** **?解释:将数据库的id根据n个hash函数存储到对应的bitmap二进制数组里面,然后通过修改为1的标志来进而判断位置是否相同来确定是否存在对应的key在此redis里面,从而达到了减少扫描redis内存数据的方案。(确定无法一定不存在的key)。** **? ? 2.持久层查询不到就缓存空结果,有效时间为数分钟。(存储空结果),防止大量查询DB** 雪崩 **????雪崩:缓存大量失效的时候,引发大量查询数据库。** 解决办法: **? ? 1.用锁/分布式锁或者队列串行访问** **? ? 2.缓存失效时间均匀分布** **????3.缓存预热,在启动或者初始化 加载一些缓存数据进入,防止大量去查询访问DB** **? ? 4.二级双层缓存机制,当一级失效则去访问二级远程的MemoryCache机制。** [热点key] **? ? 热点key:某个key访问非常频繁,当key失效的时候有大量线程来构建缓存,导致负载增加,系统崩溃。** 解决办法: ① 使用锁,单机用synchronized,lock等,分布式用分布式锁。 ② 缓存过期时间不设置,而是设置在key对应的value里。如果检测到存的时间超过过期时间则异步更新缓存。 ③ 在value设置一个比过期时间t0小的过期时间值t1,当t1过期的时候,延长t1并做更新缓存操作。 |
|
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/24 2:41:26- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |