欢迎光临
我们一直在努力

Redis第三篇

个人理解,如有错误请见谅,欢迎大佬指正。

一、缓存异常三大问题

缓存穿透查“不存在”,缓存击穿锁“一个点”,缓存雪崩崩“一整片”

对比维度缓存穿透缓存击穿缓存雪崩
问题本质 查的数据根本不存在 一个热点key突然过期 大量key同时过期或Redis宕机
典型场景 恶意攻击(用-1连续请求) 秒杀商品到期那一瞬间 批量导入缓存设了相同TTL
核心解法 布隆过滤器 + 空值缓存 热点永不过期 + 互斥锁 TTL加随机值
难度

布隆过滤器:使用BitMap作为布隆过滤器,将目前所有可以访问到的资源通过简单的映射关系放入到布隆过滤器中(哈希计算),当一个请求来临的时候先进行布隆过滤器的判断,如果有那么才进行放行,否则就直接拦截

空值缓存:如果查询缓存和数据库的数据没有找到,则直接设置一个默认值(可以是空值)存到缓存中,这样第二次读取缓存时就会获取到默认值,而不会继续访问存数据库

热点永不过期:监控数据,实时调整:监控哪些数据是热门数据,实时的调整key的过期时长

互斥锁:热点key过期时,只让一个线程去查库重建缓存,其他线程等待结果,防止全部打垮数据库

TTL加随机值:将缓存失效时间分散开,比如可以在原有的失效时间基础上增加一个随机值,比如1-5分钟随机,这样每一个缓存的过期时间的重复率就会降低,就很难引发集体失效的事件

二、双写一致性

3种常用的缓存读写策略详解

1.Cache Aside Pattern(旁路缓存模式)
Cache Aside Pattern 是我们平时使用比较多的一个缓存读写模式,比较适合读请求比较多的场景
Cache Aside Pattern 中服务端需要同时维系 db 和 cache,并且是以 db 的结果为准
​写​:
先更新 db
然后直接删除 cache 。
读 :
从 cache 中读取数据,读取到就直接返回
cache 中读取不到的话,就从 db 中读取数据返回
再把数据放到 cache 中
2.Read/Write Through Pattern(读写穿透)
只更新缓存,由缓存自己同步更新数据库
写:
先查 cache,cache 中不存在,直接更新 db
cache 中存在,则先更新 cache,然后 cache 服务自己更新 db(​同步更新 cache 和 db​)
读:
从 cache 中读取数据,读取到就直接返回
读取不到的话,先从 db 加载,写入到 cache 后返回响应
3.Write Behind Pattern(异步缓存写入)
只更新缓存,由缓存自己异步更新数据库

怎么解决读写

1.若一致性要求高:强一致方案
采用redisson实现的读写锁
在读的时候添加共享锁,可以保证读读不互斥,读写互斥(其他线程可以一起读,但是不能写)。当我们更新数据的时候,添加排他锁,它是读写,读读都互斥(其他线程不能读也不能写),这样就能保证在写数据的同时是不会让其他线程读数据的,​避免了脏数据​
2.延时双删
先删除缓存,再写数据库,然后线程休眠一段时间(比如500毫秒),最后再次删除缓存。休眠时间的确定需要评估项目读数据业务逻辑的耗时,并考虑Redis和数据库主从同步的耗时
​优缺点​:这种策略能在一定程度上解决数据不一致的问题,但增加了写请求的耗时,并且在最差的超时时间内,数据仍可能存在不一致性
3.先写db再删除缓存策略(推荐)
​推荐理由​:这是实时性最好的方案,适用于对并发和实时一致性要求较高的场景。如果删除Redis失败,则可以通过重试机制来解决
​执行流程​:先执行数据库的更新操作,成功后立即删除Redis中的对应缓存
​优缺点​:虽然在极少数情况下会出现数据不一致的情况,但其条件相对苛刻,是实时性要求下的最佳选择

三、数据过期策略 vs 淘汰策略

过期策略管“该不该删”,淘汰策略管“满了删谁”

对比维度惰性删除定期删除数据淘汰策略(八种)
触发时机 访问key时检查 定时任务每秒轮询一部分 内存满了触发
删除对象 已过期的key 已过期的key 任意key(按策略挑)
优点 对CPU友好 对内存友好 保证Redis不会OOM
缺点 过期key没被访问就永远占内存 轮询频率不好把握 可能删掉不该删的热点数据
比喻 快递到了才拆,发现过期才扔 保洁每小时抽查一批 冰箱满了,按规则扔东西

八种淘汰策略速记:

类型策略名一句话
不淘汰 noeviction 满了直接报错
全体key allkeys-lru 淘汰最久没用的
全体key allkeys-lfu 淘汰使用次数最少的
全体key allkeys-random 随机淘汰
带TTL的 volatile-lru 有过期时间的,挑最久没用的删
带TTL的 volatile-lfu 有过期时间的,挑用得最少的删
带TTL的 volatile-random 有过期时间的,随机删
带TTL的 volatile-ttl 有过期时间的,挑快过期的删

LRU(​least recently used​)的意思就是最少最近使用,用当前时间减去最后一次访问时间,这个值越大则淘汰优先级越高
LFU(​least frequently used​)的意思是最少频率使用。会统计每个key的访问频率,值越小淘汰优先级越高
选型建议:

  • 纯缓存,数据库都有备份 → allkeys-lru
  • 有些缓存数据很重要不能丢 → volatile-lru
  • 热点数据非常集中 → allkeys-lfu
赞(0)
未经允许不得转载:171主机测评 » Redis第三篇
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址