最近通过同学,突然知道服务器的缓存有很多猫腻,这里通过网上查询其他人的资料,进行记录:

缓存策略

比较简单的缓存策略:

1.失效:应用程序先从cache取数据,没有得到,则从数据库中取数据,成功后,放到缓存中。

2.命中:应用程序从cache中取数据,取到后返回。

3. 更新:先把数据存到数据库中,成功后,再让缓存失效。

4. 数据库不存在:缓存中存放null值,避免继续请求数据库,设置较短的过期时间

5. 过期时间:每次缓存设置过期时间,避免意外的脏数据

说明:

1. 为什么不先删除缓存数据,后更新?

答:避免出现脏数据(主要原因);也避免后续数据库更新失败,则不需要更新缓存(次要原因)

2. 为什么更新完数据库后,设置缓存失效,而不更新缓存数据?

答:避免两个并发写操作,导致脏数据//redis为单线程操作,不存在这种情况

3. 为什么设置过期时间?

答:1、避免意外操作,导致的脏数据。2、长时间的积累,使得缓存数据过多,影响性能

4. 数据库不存在记录,为什么要缓存中存放null值?为什么要设置较短的过期时间?

答:缓存null值,是为了避免数据库穿透。

设置较短的过期时间,是为了避免新插入该记录,导致的脏数据。

可能出现的情况

缓存穿透:

指某个key,先查cache没查到,再查db也没有查到。

这种key的存在,会导致cache一直没办法命中,压力一直打在db上面。如果访问很高频,可能会压垮DB。

解决办法其实也很简单:当查询DB没查到时,往缓存中写入一个空值(缺省值),这样第2次再查,就不会打到DB上了。(springCache-redis将结果为null的数据,保存为空字符串)

缓存并发:

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

解决:对缓存查询加锁,如果KEY不存在,就加锁,然后查DB入缓存,然后解锁;其他进程如果发现有锁就等待,然后等解锁后返回数据或者进入DB查询。(springCache-redis缓存不存在时,并发请求时,第一次请求可以进入方法,其他请求在等待,之后直接请求缓存结果,实现原理不清楚)

缓存失效:

引起这个问题的主要原因还是高并发的时候,平时我们设定一个缓存的过期时间时,可能有一些会设置1分钟啊,5分钟这些,并发很高时可能会出在某一个时间同时生成了很多的缓存,并且过期时间都一样,这个时候就可能引发一当过期时间到后,这些缓存同时失效,请求全部转发到DB,DB可能会压力过重。

解决:

其中的一个简单方案就时讲缓存失效时间分散开,比如我们可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件。(springCache-redis可以通过修改RedisCacheManager的computeExpiration方法修改过期时间,但是该设置是针对CacheConfig修改的,也就是说一个Lei,最能设置一个过期时间

缓存雪崩:

所谓“缓存雪崩“,是指缓存的机器挂了,或者数据未加载到缓存中,或者缓存同一时间大面积的失效,从而导致所有请求都去查数据库,导致数据库CPU和内存负载过高,甚至宕机。

这种问题的解决策略,一般有以下2个方面:

1). 提高缓存的HA。比如缓存的主从复制。

2). 对DB的访问实行限流、降级。

3). 缓存过期时间。以redis为例,将过期设置放到1数据库,真实数据放到0数据库,key值相同,假设都为key1。

应用程序首先判断1库这条数据是否失效,当1库标记数据库数据失效或过期,在1库中设置新的过期时间。然后从数据库取数据更新0数据库中的数据。如果判断1数据库未失效,从0数据库取出数据返回。

如何解决DB和缓存一致性问题?

答:当修改了数据库后,有没有及时修改缓存。这种问题,以前有过实践,修改数据库成功,而修改缓存失败的情况,最主要就是缓存服务器挂了。而因为网络问题引起的没有及时更新,可以通过重试机制来解决。而缓存服务器挂了,请求首先自然也就无法到达,从而直接访问到数据库。那么我们在修改数据库后,无法修改缓存,这时候可以将这条数据放到数据库中,同时启动一个异步任务定时去检测缓存服务器是否连接成功,一旦连接成功则从数据库中按顺序取出修改数据,依次进行缓存最新值的修改。

缓存策略:redis缓存之springCache的更多相关文章

  1. springboot(九) Cache缓存和Redis缓存

    1. Cache缓存 1.1 缓存的概念&缓存注解 Cache 缓存接口,定义缓存操作.实现有:RedisCache.EhCacheCache.ConcurrentMapCache等 Cach ...

  2. 本地缓存,Redis缓存,数据库DB查询(结合代码分析)

    问题背景 为什么要使用缓存?本地缓存/Redis缓存/数据库查询优先级? 一.为什么要使用缓存 原因:CPU的速度远远高于磁盘IO的速度问题:很多信息存在数据库当中的,每次查询数据库就是一次IO操作所 ...

  3. Hibernate缓存策略(一级缓存和EHcache二级缓存)

    如何配置二级缓存: 第一步:导入EHcache依赖 1)Maven项目: <!--此处使用hibernate4--> <dependency> <groupId>o ...

  4. SpringBoot学习笔记(10)-----SpringBoot中使用Redis/Mongodb和缓存Ehcache缓存和redis缓存

    1. 使用Redis 在使用redis之前,首先要保证安装或有redis的服务器,接下就是引入redis依赖. pom.xml文件如下 <dependency> <groupId&g ...

  5. Spring Cache 抽象(缓存抽象) Redis 缓存

        积少成多 ----  仅以此致敬和我一样在慢慢前进的人儿 相关内容: https://blog.51cto.com/14230003/2369413?source=dra           ...

  6. Android 开源框架Universal-Image-Loader完全解析(二)--- 图片缓存策略详解

    转载请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/26810303),请尊重他人的辛勤劳动成果,谢谢! 本篇文章 ...

  7. Hibernate缓存原理与策略 Hibernate缓存原理:

    Hibernate缓存原理: 对于Hibernate这类ORM而言,缓存显的尤为重要,它是持久层性能提升的关键.简单来讲Hibernate就是对JDBC进行封装,以实现内部状态的管理,OR关系的映射等 ...

  8. 安卓开发笔记——关于图片的三级缓存策略(内存LruCache+磁盘DiskLruCache+网络Volley)

    在开发安卓应用中避免不了要使用到网络图片,获取网络图片很简单,但是需要付出一定的代价——流量.对于少数的图片而言问题不大,但如果手机应用中包含大量的图片,这势必会耗费用户的一定流量,如果我们不加以处理 ...

  9. Web缓存基础:术语、HTTP报头和缓存策略

    简介 对于您的站点的访问者来说,智能化的内容缓存是提高用户体验最有效的方式之一.缓存,或者对之前的请求的临时存储,是HTTP协议实现中最核心的内容分发策略之一.分发路径中的组件均可以缓存内容来加速后续 ...

  10. Android 开源框架Universal-Image-Loader全然解析(二)--- 图片缓存策略具体解释

    转载请注明本文出自xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/26810303),请尊重他人的辛勤劳动成果,谢谢! 本篇文章 ...

随机推荐

  1. js获取整个屏幕的尺寸

    原文 首先获取屏幕宽度:window.screen.width;    //整个屏幕的宽度. 然后获取屏幕高度:window.screen.height;     //整个屏幕的高度. 获取可用工作区 ...

  2. 使用 Jenkins 发布 web 应用至 Tomcat

    Jenkins 的安装:https://www.cnblogs.com/jhxxb/p/11406805.html 发布流程:Git -> Maven -> Tomcat 一.基本环境 G ...

  3. [Ubuntu]18安装navicat 破解版&官方版本

    破解版本: 一.下载破解版的navicat  链接:https://pan.baidu.com/s/1ulptSderoG0EbEQpO3Adww提取码:8oc3 二.解压到桌面 在下载压缩文件之后, ...

  4. [Jenkins]局域网内可访问配置方法 -windows

    如果是把jenkins.war放在tomcat中运行,则当jenkins宿主机,启动tomcat服务之后,则直接可以通过局域网访问jenkins  下面这种情况是,直接通过jenkins.exe安装的 ...

  5. #dokcer部署code-server web版vscode+golang

    codercom/code-server:latest不支持插件在线安装 codercom/code-server:v2目前为最新版1. #创建 docker rm -f vscode docker ...

  6. Vue 子组件与子组件之间传值

    可以借用公共父元素.子组件A  this.$emit("eventName", data) 触发事件,父组件监听事件,更改父组件 data , 通过Props 传值到子组件B,子组 ...

  7. 《A Survey on Transfer Learning》迁移学习研究综述 翻译

    迁移学习研究综述 Sinno Jialin Pan and Qiang Yang,Fellow, IEEE 摘要:   在许多机器学习和数据挖掘算法中,一个重要的假设就是目前的训练数据和将来的训练数据 ...

  8. SpringBoot: 2.SpringBoot整合servlet(转)

    整合方式1:通过注解扫描完成 Servlet 组件的注册 1.编写servlet package com.bjsxt.servlet; import javax.servlet.ServletExce ...

  9. Django之logging配置

    1. settings.py文件 做开发离不开必定离不开日志, 以下是我在工作中写Django项目常用的logging配置. # 日志配置 BASE_LOG_DIR = os.path.join(BA ...

  10. unity+android权限--打开应用不弹权限,动态请求权限

    因为笔者之前的游戏需要分享图片,会请求外部储存,第一次打开游戏就会出现弹窗: 很多人对这个很敏感,怕你访问到他们的照片隐私,看到这个权限就拒绝,甚至卸载,实际上我们只是想截屏游戏内容分享给其他玩家,但 ...