缓存流程

在讲这五个问题之前,首先我们回顾下正常的缓存的使用流程

程序在处理请求时,会先从缓存中进行查询,如果缓存中没有对应的key,则会从数据库中查询,如果查询到结果,并将查询结果添加到缓存中去,反之不缓存。流程就不多解释了,基于这个我们展开下面的问题。


缓存穿透

产生原因

当查询一个一定不存在的key时,由于不能命中缓存,所以要查询数据库,但是这个key又不存在,所以查询不到结果,不会缓存。于是就有了利用这种一定不存在的key作为查询条件,对系统进行攻击,增加数据库压力,这种现象称为缓存穿透

解决方法

  1. 布隆过滤
    首先要规范key的命名,对不规范的key直接过滤掉,并对所有可能的key以hash形式存储到一个足够大的bitmap中,不存在的数据会被此bitmap拦截,以避免查询数据库。
  2. 缓存空对象
    意思很简单,就是对返回数据为空的情况也进行缓存,并设置一个很短的过期时间,这样也能起缓解作用。但是这也会产生下面两个问题:

    • 缓存空对象意味着需要更多的存储空间,可再缩短缓存时间,过期自动剔除
    • 导致缓存与数据库不一致,比如某个key:a查询时还没有数据,这时会缓存空值,但是其他某个流程已走完,数据已添加到了数据库中,这时访问依旧会返回空值,因为缓存还没过期,所以解决方法就是增删改时也进行缓存的刷新

缓存雪崩

产生原因

当大批量缓存集中在同一时间内失效(或者redis宕机),产生大量缓存穿透,此时又有请求并发袭来,查询压力瞬间都落在了数据库上,此时就产生了缓存雪崩

解决方法

  1. 失效时间加随机值
    给缓存失效时间加一个随机值,避免集体失效
  2. 实现redis高可用
    通过对redis实现集群搭建来避免部分机器宕机导致redis不可用的情况
  3. 分布式锁或分布式队列
    保证缓存单线程写,并在没有获取锁的线程中一直轮询缓存,直到超时

缓存击穿

产生原因

缓存击穿是指缓存中没有但是数据库中有的数据(通常是缓存到期),由于并发,未能从缓存读到数据,从而引起数据库鸭梨瞬间增大

解决方法

  1. 设置热门缓存数据永不过期
    这里永不过期有两层意思:

    • 不设置过期时间或超长缓存时间即物理上不过期
    • 在缓存对象上添加一个标识过期时间的属性,在获取数据后校验过期时间,如果已过期则异步去更新改缓存
      这种方式可能会出现数据脏读(在缓存更新期间取到旧数据)的情况,视业务而定使用与否
  2. 分布式锁或分布式队列
    保证缓存单线程写,并在没有获取锁的线程中一直轮询缓存,直到超时

缓存一致性

如果对数据有强一致性要求的,那就不要使用缓存了


缓存并发竞争

产生原因

多个子系统set同一个key,导致产生并发竞争

解决方法

  1. 对key没有顺序要求
    使用分布式锁实现
  2. 对key有顺序要求
    将key对应的值带上时间戳
  3. 异步队列
    放入队列中,串行set就行

Redis-缓存穿透、缓存雪崩、缓存击穿、缓存一致性、并发竞争的更多相关文章

  1. Redis缓存穿透和雪崩

    缓存穿透 用户想要查询一个数据 在redis缓存数据库中没有获取到 就会向后端的数据库中查询. 当用户很多 都去访问后端数据库的话,这就会给数据库带来很大的压力. 常见场景:秒杀活动 等 解决方法: ...

  2. 缓存穿透、雪崩、热点与Redis

    (拼多多问:Redis雪崩解决办法) 导读:互联网系统中不可避免要大量用到缓存,在缓存的使用过程中,架构师需要注意哪些问题?本文以 Redis 为例,详细探讨了最关键的 3 个问题. 一.缓存穿透预防 ...

  3. Redis系列(八)--缓存穿透、雪崩、更新策略

    1.缓存更新策略 1.LRU/LFU/FIFO算法剔除:例如maxmemory-policy 2.超时剔除,过期时间expire,对于一些用户可以容忍延时更新的数据,例如文章简介内容改了几个字 3.主 ...

  4. redis的穿透和雪崩

    穿透: 从缓存中查询一个数据,查到为空,需要每次都去数据库中查询.而从数据库中查询出来也为空,也就不写入缓存.导致一个不存在的数每次都去数据库中查询,造成db系统很大压力 造成缓存穿透 解决:如果从数 ...

  5. 深入了解Redis(7)-缓存穿透,雪崩,击穿

    redis作为一个内存数据库,在生产环境中使用会遇到许多问题,特别是像电商系统用来存储热点数据,容易出现缓存穿透,雪崩,击穿等问题.所以实际运用中需要做好前期处理工作. 一.缓存雪崩 1.概念 缓存雪 ...

  6. Redis缓存雪崩、缓存穿透、缓存击穿、缓存降级、缓存预热、缓存更新

    Redis缓存能够有效地加速应用的读写速度,就DB来说,Redis成绩已经很惊人了,且不说memcachedb和Tokyo Cabinet之流,就说原版的memcached,速度似乎也只能达到这个级别 ...

  7. Redis高级应用解析:缓存穿透、击穿、雪崩

    1 背景 像我们去面试一些大公司的时候,就会遇到一些关于缓存的问题.可能很多同学都是接触过,多多少少了解一些,但是如果没有好好记录这些内容,不熟练精通的话,在真正面试的时候,就很难答出来了. 在我们的 ...

  8. SpringBoot微服务电商项目开发实战 --- Redis缓存雪崩、缓存穿透、缓存击穿防范

    最近已经推出了好几篇SpringBoot+Dubbo+Redis+Kafka实现电商的文章,今天再次回到分布式微服务项目中来,在开始写今天的系列五文章之前,我先回顾下前面的内容. 系列(一):主要说了 ...

  9. Redis中几个简单的概念:缓存穿透/击穿/雪崩,别再被吓唬了

    Redis中几个“看似”高大上的概念,经常有人提到,某些好事者喜欢死扣概念,实战没多少,嘴巴里冒出来的全是高大上的名词,个人一向鄙视概念党,呵呵! 其实这几个概念:缓存穿透/缓存击穿/缓存雪崩,有一个 ...

  10. Redis缓存穿透,缓存击穿,缓存雪崩,热点Key

    导读 使用Redis难免会遇到Redis缓存穿透,缓存击穿,缓存雪崩,热点Key的问题.有些同学可能只是会用Redis来存取,基本都是用项目里封装的工具类来操作.但是作为开发,我们使用Redis时可能 ...

随机推荐

  1. Python--day65--Django框架介绍

    原文链接:http://www.cnblogs.com/liwenzhou/p/8296964.html 做web开发用的是MVC框架: Django框架简介 MVC框架和MTV框架(了解即可) MV ...

  2. linux进程简单睡眠

    当一个进程睡眠, 它这样做以期望某些条件在以后会成真. 如我们之前注意到的, 任何睡 眠的进程必须在它再次醒来时检查来确保它在等待的条件真正为真. Linux 内核中睡眠的 最简单方式是一个宏定义, ...

  3. ZR1050

    ZR1050 http://www.zhengruioi.com/problem/1030 题目大意: 给定一棵带点权的树,求所有联通块的点权和的平方的和 \(n \le 10^5\) 题解 首先,关 ...

  4. C# 文件在数据库 的 存取

    ... /// <summary> /// 获取数据库Image字段数据,保存到本地 /// </summary> /// <param name="sende ...

  5. LuoguP5464 缩小社交圈

    LuoguP5464 缩小社交圈 背景:洛谷七月月赛T4 题目大意给定\(n\)个点,每个点的权值对应着一个区间\([l_i,r_i]\),两个点\(i,j\)有边当且仅当他们权值的并集不为空集,问有 ...

  6. [HNOI2019]白兔之舞

    memset0 多合一无聊题 mod k=t,并且k是p-1的约数 单位根反演石锤了. 所以直接设f[i]表示走i步的方案数, 然后C(L,i)分配位置,再A^i进行矩乘得到f[i] 变成生成函数F( ...

  7. Sending Packets LightOJ - 1321 (期望计算)

    题面: Alice and Bob are trying to communicate through the internet. Just assume that there are N route ...

  8. Squid使用账号密码进行认证

    Squid 3.5支持ssl代理,为保证安全和滥用,可以使用简单的认证. Step1:在squid的配置文件中,添加如下: auth_param basic program /usr/lib64/sq ...

  9. 关于instanface的问题

    nstanceof关键字来判断某个对象是否属于某种数据类型.报错  代码如下 package cn.lijun.demo3; import cn.lijun.demo.Person;import cn ...

  10. slim中返回结果加密的

    //返回结果不加密 $this->get("/open]",function (Request $request, Response $response, $args) {  ...