1. 缓存的收益与成本

1. 收益:

  • 加速读写

    • 读缓存中的数据要比读数据存储位置的速度要快。(例如:寄存器-内存,内存-磁盘)
  • 降低后端负载

    • 如果不加缓存的话,并发的压力会直接加到后端数据库上,并发较大的时候,数据库可能会hold不住,而这里可以通过增加一层缓存,通过直接访问缓存不仅访问速度更快,而且减少了io次数,减少了数据库的压力。

2. 成本:

  • 数据不一致:

    • 缓存层是数据层的时间窗口不一致,和更新策略有关。
  • 代码维护成本:

    • 多了一层缓存逻辑
  • 运维成本:

    • 例如Redis Cluster…

2. 缓存更新策略

1. LRU/LFU/FIFO(一致性差,维护成本低)

2. 超时剔除: 例如expire(一致性差,维护成本低)

对于一些可以容忍数据不一致性的情况,可以使用这种策略。

3. 主动更新:开发控制生命周期(一致性较强,维护成本较高)

可以利用发布-订阅这种思想,在缓存来监听数据是否发生变化,若发生变化则失效. (例如volatile关键字的实现,缓存一致性协议中的嗅探机制,就是使用的这一策略, 也可利用消息队列来维护最终一致性)

低一致性: 最大内存和淘汰策略
高一致性:超时剔除和主动更新结合,最大内存和淘汰策略兜底(防OOM)。

3. 缓存的粒度控制

缓存的粒度,以缓存mysql中的数据为例,例如查询用户信息操作频繁,那么应该缓存用户信息的所有属性(select *) 还是应该缓存用户信息的部分属性(例如 select id, name, gender, age,…) 这就是一个粒度的选择.

  • 1. 通用性:全量属性更好

    • 将来可能有新需求,方便维护
  • 2. 占用空间:部分属性更好

4. 缓存穿透 - 大量请求不命中

4.1 问题:

当请求到来时,会先去查缓存,缓存中没有,然后才会“穿过”缓存层访问数据库,如果数据库中存有请求的结果,那么会将结果数据写到缓存中。 但如果访问的是数据库中也没有的记录,那么缓存中也不会存储。 当有大量请求访问数据库中不存在的数据时,那么缓存也就形同虚设,大量的并发直接落在了数据库上。

4.2 产生的原因:

1. 业务代码自身的问题

例如对于一些不合理的查询请求在业务代码层面上没有过滤掉等。

2. 恶意攻击、爬虫等

4.3 如何发现:

1. 业务的响应时间

如果出现了穿透,请求打到了存储层上,响应时间一定会收到影响。

2. 采集相关指标(对缓存进行监控):总调用数、缓存层命中数、存储层名中数

4.4 解决方法

方法一:把查询空结果也给缓存起来

  • 但这样会出现两个问题:

    1. 对于恶意攻击来说,他们可以通过组合不同的键来查询空结果,所以穿透依然无法避免。
    2. 如果在查询某个关键的key的时候,查询接口因为一些意外原因(如网络延迟过大)而导致了查询到了空结果,在把这个空结果给缓存了之后,在其失效之前,对于这个key的查询得到的结果总是空的,但这个期间,有可能查询接口又恢复正常了(但却因为缓存缓存了空结果,所以还是查询不到)。

方法二: 布隆过滤器拦截

布隆过滤器是一种数据结构,比较巧妙的概率型数据结构(probabilistic data
structure),特点是高效地插入和查询,可以用来告诉你 “某样东西一定不存在或者可能存在”。


因此,在查询的时候,先去布隆过滤器查询,只有对于通过了布隆过滤器的查询,才会真正的去执行查询. 但这并不能100%的过滤掉所有空查询,因为布隆过滤器可以保证不通过的一定不存在,但不能保证通过的一定存在。

缓存穿透应该是
当数据库中没有某个key对应的value时,缓存中也不会有该value的缓存。所以大量的对该value的查询该的请求会绕过缓存,直接查询数据库。

缓存中一般存的是 key+value ,但是布隆过滤器却可以告诉你 key
对应的value在数据库中存不存在,如果不存在就不用查询数据库了。

拿redis为例子: 请注意,用 redis 也可以做到判断 key 对应的value
在数据库中存不在,那就是把数据库里的所有value对应的key都储存在redis
中,而value可以为空,然后判断下key.IsExists()就可以了,但是这无疑会浪费大量空间,因为存储了数据库中所有的key。而且这也不符合缓存的初衷:咱不能暴力的把所有key都存下来,而是查询了啥key,我们缓存啥key。

而布隆过滤器是一种非常高效的数据结构,把所有数据库的value对应的key
存储到布隆过滤器里,几乎不消耗什么空间,而且查询也是相当的快!但是请注意,它只能判断 key 是否存在(而且会有一定的误差)。

所以一个查询先通过布隆顾虑器判断key是否存在(key 对应的value是否存在数据库中),如果不存在直接返回空就好了。

那么布隆过滤器是怎么做到几乎不消耗空间来储存所有的key,并快速判断特定的key是否存在呢?

其实原理很简单,布隆过滤器 只是一个 byte数组,再加上几个映射函数。

每个key 都通过一系列映射函数,得到一系列的的值k,然后在这个byte数组上的把k下标的值变成1。

当要判断key是否存在时,通过映射函数映射得到的一系列k,查看byte数组相应下标k对应的值是否为1,如果有一个不为1,那么一定不存在。如果都是1
,那么可能存在。为什么可能而不是一定呢?因为这是一个误差问题,有可能别的key把某个k的位置变成了1,key越多时,误差越大。但是放心不会很大的,这是可以控制的,byte数组越长,误差越小。

5. 缓存雪崩

5.1 问题

一般情况下,缓存层将接受大量的服务请求,存储层只接受比较少的服务请求,但当缓存层发生异常/脱机(总之暂时无法工作)或是是指在某一个时间段,缓存集中过期失效,那么流量直接压向后端组件(例如数据库,或第三方API),造成级联故障。

级联故障的解释:
网络中,一个或少数几个节点或连线的失效会通过节点之间的耦合关系引发其他节点也发生失效,进而产生级联效应,最终导致相当一部分节点甚至整个网络的崩溃,这种现象就称为级联失效,有时也形象称之为“雪崩” 。

5.2 优化方案

1. 保证缓存的高可用性

例如 Redis的主从机制,主机挂了从机上.

  • Redis Sentinel
  • Redis Cluster
  • 主从漂移

2. 依赖隔离组件为后端限流

  • Hystrix这种隔离组件
  • 使用线程池/信号量隔离组件
  • 使用Guava提供的限流API(令牌桶,漏桶)

3. 提前演练:例如压力测试

4. 数据预热

数据加热的含义就是在正式部署之前,我先把可能的数据先预先访问一遍,这样部分可能大量访问的数据就会加载到缓存中。在即将发生大并发访问前手动触发加载缓存不同的key,设置不同的过期时间,让缓存失效的时间点尽量均匀。

6. 无底洞问题优化*

6.1 问题

加机器之后,性能不但没有提升,反而下降了。(因为加的机器多了,网络请求次数也多了,开销也大了)

6.2 优化IO的几种方法

  1. 命令本身优化:例如慢查询keys、hgetall bigkey
  2. 减少网络通信次数(无底洞问题主要优化的位置)
  3. 降低接入成本:例如客户端长连接/连接池、NIO等

6.3 四种批量优化的方法

  1. 串行meget
  2. 串行io
  3. 并行io
  4. hash_tag

Redis缓存雪崩/穿透/击穿相关推荐

  1. Redis 缓存雪崩、击穿、穿透

    Redis 缓存雪崩.击穿.穿透 文章目录 Redis 缓存雪崩.击穿.穿透 一.Redis基础 Redis基本数据类型.操作 二.面试相关问题 1.小伙子您好,看你简历上写了你项目里面用到了Redi ...

  2. 面试填坑之Redis无底洞(一、Redis缓存雪崩、击穿、穿透)

    Redis缓存雪崩.击穿.穿透 学习自大佬:https://blog.csdn.net/qq_35190492/article/details/102889333 https://www.cnblog ...

  3. redis缓存雪崩、击穿、穿透

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言 一.redis缓存雪崩 二.redis缓存击穿 三.redis缓存穿透 前言 主要是介绍一下redis缓存雪崩.击穿. ...

  4. 如何解决Redis缓存雪崩、击穿与穿透

    Redis最常用使用的场景就是作为业务系统的缓存,既然是作为缓存,那么就不免会碰到缓存常见的问题,即雪崩.击穿与穿透,什么是缓存雪崩.击穿与穿透以及如何解决这几个问题呢?今天我们一起来探讨一下! 一. ...

  5. 关于缓存雪崩\穿透\击穿等一些问题

    前言 设计一个缓存系统,不得不要考虑的问题就是:缓存穿透.缓存击穿与失效时的雪崩效应. 缓存穿透 缓存穿透是指查询一个一定不存在的数据,由于缓存是不命中时被动写的,并且出于容错考虑,如果从存储层查不到 ...

  6. 缓存 雪崩 穿透 击穿

    缓存雪崩 原因:缓存雪崩是并发量过大带来的一系列的雪崩效应.大量的请求涌入缓存导致缓存无法处理挂掉,接着大量的请求会涌入数据库导致数据库挂掉. 分析:处理此问题的关键就是避免并发量大的时候缓存不要挂掉 ...

  7. 5redis-----------redis高级--GEO-查询附近的人、基数统计算法HLL 、布隆过滤器、缓存雪崩穿透击穿-------全栈式开发44

    redis高级 一.GEO查询附近的人 二.基数统计算法-HyperLogLog 三.布隆过滤器 四.缓存雪崩&缓存穿透 (一)缓存雪崩 (二)缓存穿透 (三)缓存击穿 一.GEO查询附近的人 ...

  8. Redis缓存知识-穿透、击穿、雪崩

    目录 一.Redis介绍 二.Redis做缓存服务器 三.缓存穿透&击穿&雪崩 1.缓存穿透 2.缓存击穿 3.缓存雪崩 大家好,我是杨叔.每天进步一点点,关注我的微信公众号[程序员杨 ...

  9. Redis缓存雪崩缓存击穿缓存穿透

    Redis缓存雪崩&缓存击穿&缓存穿透 一 缓存更新策略 二 缓存雪崩 三 缓存击穿 四 缓存穿透 一 缓存更新策略 目前redis缓存更新存在3种主流策略,分别是:内存淘汰.超时剔除 ...

  10. 老司机带你玩转面试(2):Redis 过期策略以及缓存雪崩、击穿、穿透

    前文回顾 建议前一篇文章没看过的同学先看下前面的文章: 「老司机带你玩转面试(1):缓存中间件 Redis 基础知识以及数据持久化」 过期策略 Redis 的过期策略都有哪些? 在聊这个问题之前,一定 ...

最新文章

  1. 我是如何根据豆瓣api来理解Restful API设计的
  2. Pri3D:一种利用RGB-D数据固有属性完成3D场景感知的表示学习方法
  3. python 字符串,字符串运算,比较,索引,切片等
  4. Python进阶7——字典与集合
  5. 公务员要过英语六级吗计算机,报考2020年国家公务员考试,必须要过英语四六级吗?...
  6. NBA史上薪水最高球员排行榜
  7. android nuwa2,android热更新
  8. Oracle索引知识学习笔记
  9. matlab小区制移动通信网,LTE习题 - 无线移动 - 通信人家园 - Powered by C114
  10. adobe Director的一些快捷键(direct_Shortcut)
  11. Windows 下 XDebug 手工配置
  12. 阿里巴巴小程序繁星计划专题上线,汇集最优扶持资源与最新资讯!
  13. 基于ZigBee的城市照明监控系统网关节点的软硬件设计
  14. VS2017安装CLR
  15. 第七周-C语言 求方程的共轭复根
  16. ZMQ专题学习之六:libzmq的订阅代理模式通信方式
  17. Servlet入门到入坟 一站式基础及进阶——SpringMVC没它都不行 你确定不来看看——囊括初学基础以及进阶
  18. 【前端学习 Vue (8) 什么是SSR】
  19. Mac Chrome浏览器快捷键大全
  20. ESlint 自动格式化代码 补缺代码 添加空格

热门文章

  1. Intel Thunderbolt 3 接口介绍
  2. 【路径规划】A*三维全局路径规划(附Python实现源码)
  3. EXEL表格读取 按键精灵
  4. Java 关于java.util.LinkedHashMap cannot be cast to 实体类问题答案
  5. 既要面子,也要里子,车企成不了自动驾驶的“独行侠”
  6. PLM产品生命周期管理,包含哪些阶段?
  7. 新美大--软件测试--《社招、校招jd、公司具体介绍、培训发展、关于实习是什么,要求及常见问题、校招行程、校招常见问题》整理
  8. python调用gephi_如何将python代码连接到gephi?
  9. phython学习资料
  10. 简单了解cri,runtimes,CRI,shim