zoukankan      html  css  js  c++  java
  • 缓存策略

    比较简单的缓存策略:

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

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

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

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

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

    说明:

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

        答:假设先写数据库,再淘汰缓存:第一步写数据库操作成功,第二步淘汰缓存失败,则会出现DB中是新数据,Cache中是旧数据,数据不一致。

              假设先淘汰缓存,再写数据库:第一步淘汰缓存成功,第二步写数据库失败,则只会引发一次Cache miss。

              第二次淘汰缓存的目的是避免写数据库期间,有新的缓存添加。当然,如果这种情况下,二次淘汰缓存失败,仍然有可能有脏数据……

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

       答:避免两个并发写操作,导致脏数据

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

        答:避免意外操作,导致的脏数据

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

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

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

    其他策略:

    1. DB中间件监听DB变化,更新缓存:

        现在有种新的办法就是利用DB中间件监听DB变化(比如阿里的Canal中间件,点评的Puma),从而对缓存进行更新。

        这种办法的一个好处就是:把缓存的更新逻辑,和业务逻辑解藕。业务只更新DB,缓存的更新被放在另外一个专门的系统里面。

    缓存穿透:

    所谓“缓存穿透“,就是指某个key,先查cache没查到,再查db也没有查到。

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

    解决办法其实也很简单:当查询DB没查到时,往缓存中写入一个空值(缺省值),这样第2次再查,就不会打到DB上了。

    缓存雪崩:

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

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

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

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

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

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

    参见:https://coolshell.cn/articles/17416.html

             http://blog.csdn.net/chunlongyu/article/details/53384933

             http://api.crap.cn/index.do#/web/article/detail/web/ARTICLE/7754a002-6400-442d-8dc8-e76e72d948ac

  • 相关阅读:
    Golang里边的map变量是什么?
    Golang map的底层实现
    方法和函数的区别
    Golang 对 对象和指针 的理解
    React 部分
    前端开发概述、html、css基础
    服务器核心知识
    常用模块8.7
    2017.8.2迭代器和生成器
    2017.7.18可变/不可变类型,符号运算及其流程控制
  • 原文地址:https://www.cnblogs.com/Jtianlin/p/8315953.html
Copyright © 2011-2022 走看看