zoukankan      html  css  js  c++  java
  • 缓存策略:redis缓存之springCache

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

    缓存策略

    比较简单的缓存策略:

    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和缓存一致性问题?

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

  • 相关阅读:
    使用putty上传下载文件(pscp)
    《Pro Express.js》学习笔记——app.params中间件
    《Pro Express.js》学习笔记——Express框架常用设置项
    《Pro Express.js》学习笔记——Express服务启动常规七步
    WebStorm常用配置
    ES6模块加载
    NodeJs使用asyncAwait两法
    Redis各类型应用场景
    Redis概述
    《Pro Express.js》学习笔记——概述
  • 原文地址:https://www.cnblogs.com/jaxlove-it/p/8883359.html
Copyright © 2011-2022 走看看