redis雪崩击穿穿透解决方案20200827
2020-09-10 13:45:29 0 举报
AI智能生成
redis雪崩、击穿、穿透解决方案20200827
作者其他创作
大纲/内容
应用场景
1. 秒杀库存扣减
2. APP首页的访问流量高峰
3. 与memcache的区别
基础知识
数据结构
5种基本数据结构 :Sting、Hash、list、Set、SortedSet
其他数据结构 : HyerLoglog、Geo、Pub/Sub
用于防止缓存击透的数据结构:Redis Module、像BloomFiter、RedisSearch、Redis-ML
设置key 值过期:setRedis ( Key ,value,time + Math.random()*10000) : expire
分布式锁
先拿setnx来争抢锁,抢到之后再用expire给锁加一个过期时间防止锁忘记了释放
如果在setnx之后执行expire之前进程意外crash或者要重启维护。把setnx和expire合成一条指令来用的
keys命令
Redis的单线程的。keys指令会导致线程阻塞一段时间 ;线上服务会停顿,直到服令执行完毕。服务才能恢复
scan将令可以无阻塞的提取出指定模式的key列表,但是会有一定的重复率,
在客户端做一次去重就可以了; 但是整体所花费的时间会比直接用keys指令长
在客户端做一次去重就可以了; 但是整体所花费的时间会比直接用keys指令长
SMEMBERS命令可以返回集合键当前包含的所有元素
SCAN 这类增量式法代命令来说。因为在对键进行增量式选代的过程中,
键可能会被修改,所以增量式达代命令只能对被返回的元索提供有限的保证。
键可能会被修改,所以增量式达代命令只能对被返回的元索提供有限的保证。
异步队列
list结构作为队列。rpush生产消息。Ipop消费消息。当Ipop没有消息的时候, 要造 当sleep一会再重试。_
list还有个指令叫blpop ,在没有消息的时候,它会阻塞住直到消息到来
pub/sub主题订阅者模式,可以实现1.N的消息队列,实现生产一次,消费多次
pub/sub主题订阅者模式, 消费者 下线的情况下生产的消息会丢失 ,得使用专业的消息队列如RocketMQ
延时队列
sortedset ,拿时间戳作为score,消息内容作为key调用zadd来生产消息。
消费者用zrangebyscore指令获取N秒之前的数据轮询进行处理,
消费者用zrangebyscore指令获取N秒之前的数据轮询进行处理,
持久化
RDB做镜像全量持久化,AOF做增量持久化。因为ROB会耗费较长时间;不够实时;在停机的时候会
导致大量丢失数据,所以需要AOF来配合使用。在redis实例重启时,会使用RDB持久化文件重新构建内存,再
使用AOF重放近期的操作指令来实现完整的恢复重启之前的状态
导致大量丢失数据,所以需要AOF来配合使用。在redis实例重启时,会使用RDB持久化文件重新构建内存,再
使用AOF重放近期的操作指令来实现完整的恢复重启之前的状态
Redis本身的机制是AOF持久化开启且存在AOF文件时,优先加载AOF文件 ;AOF关闭或者AOF文件不存在时 ,
加载RDB文件 ;加载AOF/RDB文件成功后,Redis启动成功;AOF/RDB文件存在错误时,Redis启动失败并打印错误信息。
加载RDB文件 ;加载AOF/RDB文件成功后,Redis启动成功;AOF/RDB文件存在错误时,Redis启动失败并打印错误信息。
机器断电对数据丢失影响
AOF日志Sync属性的配置 。如果不要求性能,在每条写指令时都sync一下磁盘.就不会丢失数据,
但是在高性能的要求下每次都sync是不现实的,一般都使用定时sync,比如1s1次,这个时候最多就会丢失1s数据
但是在高性能的要求下每次都sync是不现实的,一般都使用定时sync,比如1s1次,这个时候最多就会丢失1s数据
RDB原理
Fork是指redis通过创建子进程来进行RDB操作,cow指的是copy on wite,子进程创建后 ,父子进程共享数期段,
父进程维续提供读写服务, 写脏的页面数据会逐渐和子进程分离开来
父进程维续提供读写服务, 写脏的页面数据会逐渐和子进程分离开来
Pipeline好处
可以将多次IO往返的时间缩减为一次,前提是pipeline执行的指令之间没有因果相关性
集群的同步机制
Redis可以使用主从同步 从从同步
第一次同步时, 主节点做一次save ;并同时将后续修改操作记录到内存bufter ;待完成后将RDB文件全量同步到复制节点
复制节点按受完成后将RDB镜像加载到内存, 加载完成后 。再通知主节点
后续的增量数据通过AOF日志同步即可 :有点类似数据库的binlog
集群高可用
Redis Sentnal着眼于高可用.在master宕机时会自动将slave提升为master。继续提供服务。
Redis Cluster着眼于扩展住.在单个redis内存不足时,使用Cluster进行分片存储
持久化
RDB
冷备
RDB 持文化机制。是对Redis中的数据执行周期性的持文化。
优点: RDB对Redis的性能影响非常小,是因为在同步数据的时候他只是fork了一个子进程去做持久化的 。
而且他在数据恢复的时候速度比AOF来的快。
而且他在数据恢复的时候速度比AOF来的快。
缺点:RDB都息快照文件,都是默认五分钟甚至更久的时间才会生成一次,这意味着你这次同步到下次同步这期间五分钟的数据都很可能全部丢失掉,
AOF则最多丢一秒的数据;RDB再生成数据快照的时候,如果文件很大,客户端可能会暂停几毫秒甚至几秒
AOF则最多丢一秒的数据;RDB再生成数据快照的时候,如果文件很大,客户端可能会暂停几毫秒甚至几秒
AOF
热备
AOF机制对每条写入命令作为日志,以append-only的模式写入一个日志文件中
优点:AOF一秒一次去通过一个后台的线程fsync操作,那最多丢这一秒的数据。
AOF在对日志文件进行操作的时候是以append-only的方式去写的.他只是追加的方式写数据,自然就少了很多磁盘寻址的开销
AOF在对日志文件进行操作的时候是以append-only的方式去写的.他只是追加的方式写数据,自然就少了很多磁盘寻址的开销
缺点:一样的数据 . AOF文件比RDB还要大
内存淘汰机制
即过期策路
定期删除:默认100ms就随机抽一些设置了过期时间的key ,去检查是否过期,过明了就删了.
惰性删除:我不主动删 ,我懒我等你来查询了我看看你过期没,过期就删了还不给你返回, 没过期该怎么样就怎么样。
最经典的KV、DB读写模式
缓存 +数据库读写的模式
读的时候:先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应
更新的时候 。先更新数据库。然后再删除缓存
主从同步
启动一台slave的时候;他会发送一个psync命令治master ,如果是这个slave第一次连接到master ;他会触发一个全量复制。
master就会启动一个线程生成RDB快照,还会把新的写请求都缓存在内存中,RDB文件生成后,
master会将这个RDB发送给slave,slave拿到之后做的第一件事情就是写进本地的磁盘,然后加载进内存,然后master会把内存
里面的缓存的那些新命名都发给slave。
master就会启动一个线程生成RDB快照,还会把新的写请求都缓存在内存中,RDB文件生成后,
master会将这个RDB发送给slave,slave拿到之后做的第一件事情就是写进本地的磁盘,然后加载进内存,然后master会把内存
里面的缓存的那些新命名都发给slave。
集群模式
主从
读写分离,一主一从,主写从读,主从复制模式,主挂需要手动切换
哨兵+主从
基于主从模式,哨兵是一个独立的进程,作为进程,它会独立运行,通过发送命令,自动选择主
多哨兵模式,互相监控
配置:一主二从三哨兵
哨兵工作原理,通过监听,标记判断
优点:具备主从有点,主从自动切换,可用性更高,系统更健壮
Cluster 集群
分布式存储,每个节点存储不同数据,通过hash算法落到不同节点
最低配置:3主3从做集群,
哨兵+主从实现redis集群高可用,不断升级完善
集群监控:负责监控Redis master和slave进程是否正常工作。
消息通知:如果某个Redis实例有故障。那么哨兵负责发送消息作为报警通知给管理员。
故障转移:如果master node挂掉了。会自动转移到slave node上
配置中心:如果故障转移发生了,通知client客户端新的master地址,
分布式锁
以基于Zookeeper实现分布式锁。每个系统通过Zokeeper获取分布式锁,确保同一时间,只能有一个系统实例在操作某个Key_
以上用来解决因多个系统同时操作(并发) Redis带来的数据问题
缓存雪崩、击穿、穿透
雪崩
①key批量失效:大面积的缓存失效,打崩了DB
同一时间大面积失效,那一瞬间Reds跟没有一样,那这个数量级别的请求直接打到数据库几乎是灾难性的,
你想如果打挂的是一个用户服务的库 ,那其他依赖他的苦所有的接口机会都会报错,如果没做熔断等策略
基本上就是瞬间挂一片的节奏
你想如果打挂的是一个用户服务的库 ,那其他依赖他的苦所有的接口机会都会报错,如果没做熔断等策略
基本上就是瞬间挂一片的节奏
解决办法:1、批量往Reis存数据的时候。把每个Key的失效时间都加个随机值就好了。这样可以保证数据不会在
同一时间大面积失效
同一时间大面积失效
2. Reds是集群部署将热点数据均匀分布在不同的Redis库中也能避免全部失效的问题
3. 设置热点数据永远不过期;有更新操作就更新缓存就好了
穿透
②不存在的key:用户不断的发起缓存和数据库中均不存在的数据的请求;与致数据库压力过大,严重会击跨数据库
解决办法:1.增加参数校验
2.从网关层Nginx增加配道项.对单个IP每秒访问次数超出阈值的IP都拉黑。
3. 布降过滤器(Bloom Fiter )这个也能很好的防止缓存穿透的发生,他的原理也很简单 就是利用高效的
数据结构和算法快速判断出你这个Key是否在数据库中存在,不存在return,存在就去查DB刷新KV再return。
数据结构和算法快速判断出你这个Key是否在数据库中存在,不存在return,存在就去查DB刷新KV再return。
击穿
③热点key失效瞬间:非常热点key ,在不停的扛着大并发,大并发集中对这一个点进行访问 ,当这个Key在失效的瞬间.持续的大并发就穿破缓存,
直接请求数据库
直接请求数据库
1、解决方法:设置热点数据永不过期
缺点:数据不能保持最新、定时线程更新数据【不能造成数据库压力】
缺点:数据不能保持最新、定时线程更新数据【不能造成数据库压力】
2、synchronized+双重检查机制:某个key只让一个线程查询,阻塞其它线程,在同步块中,继续判断检查,保证不存在,才去查DB。
缺点: 会阻塞其它线程
缺点: 会阻塞其它线程
3、增加互斥锁
就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。
就是在缓存失效的时候(判断拿出来的值为空),不是立即去load db,而是先使用缓存工具的某些带成功操作返回值的操作(比如Redis的SETNX或者Memcache的ADD)去set一个mutex key,当操作返回成功时,再进行load db的操作并回设缓存;否则,就重试整个get缓存的方法。
与memcache区别
Redis 相比Memcached来说;拥有更多的数据结构,能支持更丰富的数据操作
Redis 只使用单核,而Memcached可以使用多核,所以平均每一个核 上Redis 在存储小数据时比Memcached性能更高
在redis3x版本,便能支持Cluster模式,而memcached没有原生的集群模式,需要依靠客户端来实现往集群中分片写入数据
学习过程
事前:Redis 高可用,主从+哨兵,Redis cluster↓避免全盘崩溃。
事中:本地ehcache缓存+Hystrix限流+降级,避免MySql被打死
事后:Redis持化RDB+AOF,一旦重启 自动从磁盘上加载数据,快速恢复缓存教据。
聚码流沙、www.jmlson.com
0 条评论
下一页