java如何解决缓存问题_4种常见的缓存问题及解决方案详解
前言
使用缓存可以缓解大流量压力,显著提高程序的性能。我们在使用缓存系统时,尤其是大并发情况下,经常会遇到一些“疑难杂症”。本文总结了一些使用缓存时常见的问题及解决方案,以后在遇到这类问题时可以作为参考,在设计缓存系统的时候也应该考虑这些常见的情况。
为了表述方便,本文以数据库查询缓存为例,使用缓存可以减小对数据库的压力。
缓存穿透
我们在使用缓存时,往往先尝试去缓存中取值,如果没有,再去数据库取值,如果数据库也没有值,则根据业务需求,返回空或者抛异常。
如果用户一直访问一个数据库不存在的数据,比如id为-1的数据,就会导致每次请求都会先去缓存查一次,然后再去数据库查一次,造成严重的性能问题。这种情况就叫缓存穿透。
解决方案
以下几种解决方案:对请求参数做校验,比如用户鉴权校验,id做基础校验,id <= 0的直接拦截。
如果查询到数据库没有值,也将对应的key存进缓存中,value为null。这样下次查询就直接从缓存返回了。但这里的key的缓存时间应该比较短,比如30s。防止后面在数据库插入了这条数据,而用户获取不到。
使用布隆过滤器,判断一个key是否已经查过了,如果已经查过了,就不去数据库查询。
缓存击穿
缓存击穿指的是,一个key的访问量非常大,比如某秒杀活动,有1w/s的并发量。这个key在某一时刻过期,那这些大量的请求就会一瞬间到数据库,数据库可能会直接崩溃。
解决方案
缓存击穿的解决方案也有几种,可以配合使用:对于热点数据,慎重考虑过期时间,确保热点期间key不会过期,甚至有些可以设置永不过期。
使用互斥锁(比如Java的多线程锁机制),第一个线程访问key的时候就锁住,等查询数据库返回后,把值插入到缓存后再释放锁,这样后面的请求就可以直接取缓存里面的数据了。
缓存雪崩
缓存雪崩指的是,在某一时刻,多个key失效。这样就会有大量的请求从缓存中获取不到值,全部到数据库。还有另一种情况,就是缓存服务器宕机,也算做缓存雪崩。
解决方案
针对上述两种情况,缓存雪崩有两种解决方案:对每个key的过期时间设置一个随机值,而不是所有key都相同。
使用高可用的分布式缓存集群,确保缓存的高可用性,比如redis-cluster。
双写不一致
在使用数据库缓存的时候,读和写的流程往往是这样的:读取的时候,先读取缓存,如果缓存中没有,就直接从数据库中读取,然后取出数据后放入缓存
更新的时候,先删除缓存,再更新数据库
所谓双写不一致,就是在发生写操作(更新)的时候或写操作之后,可能会存在数据库里面的值和缓存中的值不同的情况。
为什么更新的时候要先删除缓存,再更新数据库?因为如果先更新数据库,然后在删除缓存的时候失败了,就会造成缓存里面的值和数据库的值不一致。
然而这样并不能完全避免双写不一致问题。假设在大并发情景下,一个线程先删除缓存,然后取更新数据库,这个时候另一个线程去取缓存,发现没有值,于是去读数据库,然后把数据库旧的值设置进缓存。等第一个线程更新完数据库后,数据库里面就是新的值,而缓存里面是旧的值,所以就存在了数据不一致的问题。
一个比较简单的解决办法是把过期时间设置得比较低,这样就只有在缓存没过期之前存在数据不一致问题,在一些业务场景下也还能接受。
另一种解决方案是使用队列辅助。先更新数据库,再删除缓存。如果删除失败,就放进队列。然后另一个任务从队列中取出消息,不断去重试删除相应的key。
还有一种解决方案是使用对一个数据使用一个队列,使读写操作串行化。比如对id为n的数据建立一个队列。对这条数据的写操作,删除缓存后,放进一个队列;然后另一个线程过来了,发现没有缓存,则把这个读操作也放进这个队列里面。
欢迎大家关注我的公种浩【程序员追风】,文章都会在里面更新,整理的资料也会放在里面。
不过这样会增加程序的复杂性,串行化也会降低程序的吞吐量,可能得不偿失。一般主流的解决方案还是先删除缓存,再更新数据库。可以满足绝大部分需求。
最后
欢迎大家一起交流,喜欢文章记得点个赞哟,感谢支持!
java如何解决缓存问题_4种常见的缓存问题及解决方案详解相关推荐
- HTTP常见的状态码及解决方案详解。
转自:微点阅读 https://www.weidianyuedu.com/content/0517446524143.html HTTP中常见的各种状态码详解及解决方案 总结了一些常见的http的状 ...
- java数据存在ie中_[Java教程]解决在IE中获取数据的缓存问题,运行环境为node.js
[Java教程]解决在IE中获取数据的缓存问题,运行环境为node.js 0 2015-11-30 20:00:06 IE下默认会开启缓存策略,不管是页面还是通过ajax请求的数据都会议一个url,u ...
- 9种常见的前端跨域解决方案
9种常见的前端跨域解决方案(详解) 2019.09.02 21:54 73879浏览 一.什么是跨域? 在前端领域中,跨域是指浏览器允许向服务器发送跨域请求,从而克服Ajax只能同源使用的限制. ...
- java 三种将list转换为map的方法详解
这篇文章主要介绍了java 三种将list转换为map的方法详解的相关资料,需要的朋友可以参考下 java 三种将list转换为map的方法详解 在本文中,介绍三种将list转换为map的方法: 1) ...
- 小波基函数构造matlab,五种常见小波基函数及其matlab实现全解.docx
五种常见小波基函数及其matlab实现全解 与标准的傅里叶变换相比,小波分析中使用到的小波函数具有不唯一性,即小波函数 具有多样性.小波分析在工程应用中,一个十分重要的问题就是最优小波基的选择问题,因 ...
- Flink常见的关键技术与特性详解
转载:http://bigdata.51cto.com/art/201702/531036.htm Flink常见的关键技术与特性详解 Flink项目是大数据处理领域最近冉冉升起的一颗新星,其不同于其 ...
- 从Java程序员进阶到架构师,6大核心技能要领详解
" java架构师技能将分为如下6大环节:数据结构和算法,Java高级特性,Java web核心,数据库,Java框架与必备工具,系统架构设计. 希望能真正帮助到从程序员进阶到架构师之路的朋 ...
- java中多线程之CAS(compareAndSet),Unsafe类大白话详解.
java中多线程之CAS(compareAndSet),Unsafe类大白话详解 什么是CAS CAS原理 Unsafe类: 什么是CAS 比较并交换 在学习CAS之前,我们先了解一下JMM. ...
- java ear war_基于Java的打包jar、war、ear包的作用与区别详解
基于Java的打包jar.war.ear包的作用与区别详解 以最终客户的角度来看,JAR文件就是一种封装,他们不需要知道jar文件中有多少个.class文件,每个文件中的功能与作用,同样可以得到他们希 ...
最新文章
- 如何用excel制作xy曲线图_用Excel制作一个简易抽奖小程序,可一次抽取多人
- 在php中可以使用几种方法定义数组,PHP中数组定义的几种方法
- 牛客网题目——替换空格
- linux下安装虚拟天文馆,如何在Ubuntu 20.04、18.04中安装Stellarium 0.20.0虚拟天文馆
- WEB API 系列(二) Filter的使用以及执行顺序
- 分布式锁实现方式介绍和Zookeeper实现原理
- Java 11 的新特性(上)
- 基于R语言的贝叶斯网络模型、现代贝叶斯统计学方法
- 请确保您已登录客户机操作系统。在客户机中装载虚拟CD驱动器,启动终端,使用tar解压...
- 欧洲模拟卡车2(TruckersMP EU)测试欧服连通率的脚本
- java程序模拟红篮球概率事件
- 用C语言程序实现十进制转换为二进制
- ipad越狱后怎么还原?
- 百余门店闭门谢客,韩妆如何败给了国潮?
- Swagger使用方式,告别postman
- java读取视频_【转载】Java 后端读取视频文件获取视频流后 前端进行播放/下载...
- 金字塔原理(麦肯锡)-要点汇总
- android相机分辨率是多少合适,相机像素高一定好吗 相机像素多少合适【详解】...
- 【VRP问题】基于模拟退火遗传实现带时间窗的车辆路径规划问题
- 校园兼职网站php设计,大学生兼职网站的设计开发毕业论文.doc
热门文章
- java计算机毕业设计甜心驿站饮品信息管理源代码+数据库+系统+lw文档
- C# await 高级用法
- 在苹果系统下切换xp系统方式
- python早餐组合
- 计算机画图图形组合教案,有趣的画图工具教学设计
- conda在指定环境下安装Gurobi包
- 出行领域成侵害用户权益重灾区,星星充电上市进程或添阻
- linux在创建文件夹失败,分享一个Linux无法创建文件夹,但是目录权限却显示正常的问题和解决...
- 2021年中国短视频用户规模及头部企业分析:快手电商交易总额达6800.36亿元,同比增长78.41%[图]
- qtcp多用户同时发信息的信号处理_FPGA进行数字信号处理的相关问题有哪些?来看数字信号处理系统架构分析!...