Redis缓存雪崩,击穿,穿透以及解决方案
Redis读写过程
一般情况下,Redis都是作为client与MySQL间的一层缓存,尽量减少MySQL的读压力,数据流向如图所示:
Redis的五种数据类型及使用场景
String 这个其实没啥好说的,最常规的set/get操作,value可以是String也可以是数字。一般做一些复杂的计数功能的缓存。
hash 这里value存放的是结构化的对象,比较方便的就是操作其中的某个字段。博主在做单点登录的时候,就是用这种数据结构存储用户信息,以cookieId作为key,设置30分钟为缓存过期时间,能很好的模拟出类似session的效果。
list 使用List的数据结构,可以做简单的消息队列的功能。另外还有一个就是,可以利用lrange命令,做基于redis的分页功能,性能极佳,用户体验好。
set 因为set堆放的是一堆不重复值的集合。所以可以做全局去重的功能。为什么不用JVM自带的Set进行去重?因为我们的系统一般都是集群部署,使用JVM自带的Set,比较麻烦,难道为了一个做一个全局去重,再起一个公共服务,太麻烦了。 另外,就是利用交集、并集、差集等操作,可以计算共同喜好,全部的喜好,自己独有的喜好等功能。
sorted set 多了一个权重参数score,集合中的元素能够按score进行排列。可以做排行榜应用,取TOP N操作。
Redis都有哪些功能和使用场景?
Redis 是一个使用 C 语言开发的高速缓存数据库。
功能列表:数据缓存功能,分布式锁的功能,支持数据持久化,支持事务,支持消息队列
使用场景:记录帖子点赞数、点击数、评论数;缓存近期热帖;缓存文章详情信息;记录用户会话信息。
Redis缓存雪崩,击穿,穿透以及解决方案
分析:
这几个问题,说句实在话,一般中小型传统软件企业,很难碰到这个问题。如果有大并发的项目,流量有几百万左右。这两个问题一定要深刻考虑。
1、缓存雪崩
在同一时间缓存大面积失效,从而导致大量请求导向数据库。
- 大量请求,导致数据库处理不过来,整个系统依赖数据库的功能全部崩溃。
- 单系统挂掉,其他依赖于该系统的应用也会出现不稳定甚至崩溃。
解决方法:
大多数系统设计者考虑用加锁( 最多的解决方案)或者队列的方式保证来保证不会有大量的线程对数据库一次性进行读写,从而避免失效时大量的并发请求落到底层存储系统上。
还有一个简单方案就时讲缓存失效时间分散开。在批量往Redis存数据的时候,把每个Key的失效时间都加个随机值就好了,这样可以保证数据不会在同一时间大面积失效了!
2、缓存穿透
大量请求查询缓存中不存在的数据,导致所有的请求都怼到数据库上,从而导致整个系统依赖数据库的功能全部崩溃。
解决方法:
最常见的则是采用布隆过滤器,将所有可能存在的数据哈希到一个足够大的bitmap中,一个一定不存在的数据会被 这个bitmap拦截掉,从而避免了对底层存储系统的查询压力。
另外也有一个更为简单粗暴的方法(我们采用的就是这种),如果一个查询返回的数据为空(不管是数据不存在,还是系统故障),我们仍然把这个空结果进行缓存,但它的过期时间会很短,最长不超过五分钟。
3、缓存击穿
大量请求集中并发在一个key上,当这个key在失效的瞬间,大量并发请求直接都怼到数据库上,从而导致整个系统依赖数据库的功能全部崩溃。
缓存击穿是指一个Key非常热点,在不停的扛着大并发,大并发集中对这一个点进行访问,当这个Key在失效的瞬间,持续的大并发就穿破缓存,直接请求数据库,就像在一个完好无损的桶上凿开了一个洞。
就是这个值是数据库新增的,但是缓存中暂时还没有,这个时候刚好并发请求进来了,如果处理不当也会发生。
解决方法:
尽量少的线程构建缓存(甚至是一个) + 数据一致性 + 较少的潜在危险。有四种方法来解决这个问题:
1、使用互斥锁(mutex key)(业界比较常用)
2、"提前"使用互斥锁(mutex key)
3、"永远不过期"
4、资源保护:采用netflix的hystrix,可以做资源的隔离保护主线程池,如果把这个应用到缓存的构建也未尝不可。
作为一个并发量较大的互联网应用,我们的目标有3个:(没有最好,只有最合适)
- 加快用户访问速度,提高用户体验。
- 降低后端负载,保证系统平稳。
- 保证数据“尽可能”及时更新(要不要完全一致,取决于业务,而不是技术。)
1、对数据库访问进行限流(控制并发量)。
2、容错降级,多线程竞争获取令牌,没拿到令牌就等待。类似Lock
3、针对内存不足问题,采用redis集群方案。
四种方案对比:
解决方案 | 优点 | 缺点 |
---|---|---|
简单分布式锁(Tim yang) | 1. 思路简单 2. 保证一致性 |
1. 代码复杂度增大 2. 存在死锁的风险 3. 存在线程池阻塞的风险 |
加另外一个过期时间(Tim yang) | 保证一致性 | 同上 |
不过期(本文) | 异步构建缓存,不会阻塞线程池 | 1. 不保证一致性。 2. 代码复杂度增大(每个value都要维护一个timekey)。 3. 占用一定的内存空间(每个value都要维护一个timekey)。 |
资源隔离组件hystrix(本文) | 1. hystrix技术成熟,有效保证后端。 2. hystrix监控强大。 |
部分访问存在降级策略。 |
如何解决redis的并发竞争key问题
分析:
这个问题大致就是,同时有多个子系统去set一个key。这个时候要注意什么呢?大家思考过么。需要说明一下,博主提前百度了一下,发现答案基本都是推荐用redis事务机制。博主不推荐使用redis的事务机制。因为我们的生产环境,基本都是redis集群环境,做了数据分片操作。你一个事务中有涉及到多个key操作的时候,这多个key不一定都存储在同一个redis-server上。因此,redis的事务机制,十分鸡肋。
解决方法:
- 如果对这个key操作,不要求顺序,这种情况下,准备一个分布式锁,大家去抢锁,抢到锁就做set操作即可,比较简单。
- 如果对这个key操作,要求顺序,假设有一个key1,系统A需要将key1设置为valueA,系统B需要将key1设置为valueB,系统C需要将key1设置为valueC. 期望按照key1的value值按照 valueA-->valueB-->valueC的顺序变化。这种时候我们在数据写入数据库的时候,需要保存一个时间戳。假设时间戳如下
系统A key 1 {valueA 3:00}
系统B key 1 {valueB 3:05}
系统C key 1 {valueC 3:10}
那么,假设这会系统B先抢到锁,将key1设置为{valueB 3:05}。接下来系统A抢到锁,发现自己的valueA的时间戳早于缓存中的时间戳,那就不做set操作了。以此类推。
其他方法,比如利用队列,将set方法变成串行访问也可以。总之,灵活变通。
Redis 持久化有几种方式?
Redis 的持久化有两种方式,或者说有两种策略:
RDB(Redis Database):指定的时间间隔能对你的数据进行快照存储。
AOF(Append Only File):每一个收到的写命令都通过write函数追加到文件中。
主服务器写内存快照,会阻塞主线程的工作,当快照比较大时对性能影响是非常大的,会间断性暂停服务,所以主服务器最好不要写内存快照。
Redis缓存雪崩,击穿,穿透以及解决方案的更多相关文章
- Redis 缓存雪崩 |击穿 |穿透 概念及解决方案
一.雪崩 1.概念 指某一时间段,缓存集中过期失效,无数的请求绕开缓存,直接访问数据库. 2.解决方案 让redis数据永不过期,这种方式最可靠的.最安全的,但占用空间,内存消耗大,并且不能保持数据 ...
- redis缓存雪崩、穿透、击穿概念及解决办法
缓存雪崩 对于系统 A,假设每天高峰期每秒 5000 个请求,本来缓存在高峰期可以扛住每秒 4000 个请求,但是缓存机器意外发生了全盘宕机.缓存挂了,此时 1 秒 5000 个请求全部落数据库,数据 ...
- Redis 缓存雪崩、穿透、击穿
缓存雪崩 定义: 同一时间所有 key 大面积失效,比如网站首页的数据基本上都是同一批次去缓存的. 解决方法: ① 存的时候设定随机的失效时间. ② 服务做熔断处理(异常或着慢查询 Hystrix 限 ...
- 关于redis的几件小事(七)redis缓存雪崩与穿透
1.缓存雪崩 (1)什么是缓存雪崩 缓存雪崩指的是在同一时刻,缓存大量失效,导致大量的请求直接到了数据库,数据库压力剧增,引起系统崩溃.可能出现的情况有: ①大量的key设置了相同的过期时间,导致在缓 ...
- Redis缓存雪崩和穿透的解决方法
转载自: https://blog.csdn.net/qq_35433716/article/details/86375506 如何解决缓存雪崩?如何解决缓存穿透?如何保证缓存与数据库双写时一致的问题 ...
- Redis缓存雪崩、缓存穿透、缓存击穿、缓存降级、缓存预热、缓存更新
Redis缓存能够有效地加速应用的读写速度,就DB来说,Redis成绩已经很惊人了,且不说memcachedb和Tokyo Cabinet之流,就说原版的memcached,速度似乎也只能达到这个级别 ...
- Redis缓存雪崩、击穿、穿透
参考大佬 前言 Redis在互联网技术存储方面使用如此广泛,几乎所有的后端技术面试官都要在Redis的使用和原理方面对小伙伴们进行360°的刁难.作为一个在互联网公司面一次拿一次offer的面霸(请允 ...
- 8.了解什么是 redis 的雪崩、穿透和击穿?redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 redis 的穿透?
作者:中华石杉 面试题 了解什么是 redis 的雪崩.穿透和击穿?redis 崩溃之后会怎么样?系统该如何应对这种情况?如何处理 redis 的穿透? 面试官心理分析 其实这是问到缓存必问的,因为缓 ...
- Redis缓存的主要异常及解决方案
作者:京东物流 陈昌浩 1 导读 Redis 是当前最流行的 NoSQL数据库.Redis主要用来做缓存使用,在提高数据查询效率.保护数据库等方面起到了关键性的作用,很大程度上提高系统的性能.当然在使 ...
- [redis] -- 缓存雪崩和缓存穿透、缓存击穿问题解决方案篇
缓存雪崩 缓存同一时间大面积的失效,所以,后面的请求都会落到数据库上,造成数据库短时间内承受大量请求而崩掉 解决方案 事前:尽量保证整个redis集群的高可用性,发现机器宕机尽快补上.选择合适的内存淘 ...
随机推荐
- csapp-datalab(菜鸟小白版)
第1题: /* * bitXor - x^y using only ~ and & * Example: bitXor(4, 5) = 1 * Legal ops: ~ & * Max ...
- three.js教程1补充-gui.js库使用
gui.js是一个前端js库,对HTML.CSS和JavaScript进行了封装,学习开发的时候,借助dat.gui.js可以快速创建可手动控制三维场景的UI交互界面,打开API文档中案例体验一下就能 ...
- 关于ESLint: Delete `␍`(prettier/prettier) 错误解决方案(3种)
1.点击VSCode右下角LF/CRLF然后根据弹窗修改成LF即可 2.在.eslintrc.cjs中增加配置 "rules": { "prettier/prettier ...
- 密码学—RSA公钥算法Python程序
RSA流程 选取两个素数p,q,保密p,q 计算出n = p×q ,公开n 计算φ(n)=(p-1)(q-1) ,保密φ(n) 选择一个数e ,e满足:e < φ(n) , gcd(e,φ(n) ...
- AIRIOT物联网低代码平台如何配置三菱PLC驱动?
三菱PLC驱动配置使用三菱Melsec协议(MC协议)从三菱PLC读取数据,仅支持以太网方式.三菱PLC都可以通过此协议访问,但是需要对PLC进行设置. AIRIOT物联网低代码平台如何配置三菱PLC ...
- docker flannel网络
部署etcd github部署访问链接:https://github.com/etcd-io/etcd/releases/ ETCD_VER=v3.5.1 # choose either URL GO ...
- Vue cli之创建组件
一般在开发中,我们会人为把组件分2个目录存放,一个代表的页面组件,另一个代表页面一部分的子组件. src/ |- views/ |- Home.vue |- components/ |- App.vu ...
- windows下载安装ipopt求解器 可用于pyomo调用
方案一:采用官方编译的应用程序 官方对windows下有已经编译好的应用程序,只需要下载下来,并将ipopt的应用程序所在文件夹路径添加到系统全局环境变量就可以了.这样在利用pyomo或者其他建模工具 ...
- nonatomic 带来的线程安全问题
一.结论 一个对象对外暴露的读写属性,如果这个属性在多个线程中访问,一定会出现crash. 因此对外暴露的属性一定要考虑线程安全问题. 二.看下面的代码 下面的代码一定会crash,除非obj是ato ...
- uniapp 拨打电话功能
phoneNumber进行动态调用时候一定要添加引号,否则会报错 1 call() { 2 uni.makePhoneCall({ 3 phoneNumber: 'this.leads.tel' // ...