高并发缓存架构实战和优化

参考资料:

图灵课堂-https://vip.tulingxueyuan.cn

 

中小公司Redis缓存架构以及线上问题分析

直接写入数据库,然后更新redis;

正常低并发情况下,这种情况是暂时不会出现问题的,因为并发量并不高,不会出现各种各样的并发问题。

大厂线上大规模商品缓存数据冷热分离实战

使用缓存,主要是为了令常用的数据放到缓存中,不常用的数据最少放到缓存中,尽量提升缓存的空间利用率。

所以,就对缓存数据加上一个过期时间,这样可以让冷数据过期了节省缓存空间;同时针对查询到的数据再进行过期时间续期,让常用数据长时间停留在缓存中。

实战解决大规模缓存击穿导致线上数据库压力暴增

缓存击穿:缓存中没有,但是数据库有;就是大量请求到redis,查询不到数据,要落库查询,这样可能会导致大量的请求访问数据库,令数据库压力增长,可能会让数据库崩溃。此时可以针对缓存设置过期时间的时候,设置随机过期时间,保证少量的请求去访问数据库。

缓存穿透:缓存中没有,数据库中也没有。就是数据不存在,或者是从数据库直接物理删除,会导致查询缓存没有,数据库也没有;或者是黑客使用不存在的数据进行攻击。这样会令数据库压力暴增,可能会导致数据库崩溃。后端也可以限流,也可以设置一个IP黑名单。

或者缓存一个空的字符串,或者一个常量json串,尽量不要返回null。同时设置一个过期时间。但是这样并不会彻底避免这样的情况,同时也会让redis和数据库的请求压力增加;所以针对这样的情况可以使用布隆过滤器。

黑客攻击导致缓存穿透线上数据库宕机BUG

ddos攻击,可以进行限流操作;但是更好的方案是再加上一个布隆过滤器。

一行代码解决线上缓存穿透问题

返回一个空值,前端进行配合。

一次大V直播带货导致线上商品系统崩溃原因分析

冷门商品突然有大量的流量访问,此时针对这个key来说,压力很高;此时直接访问数据库,此时还有别的请求去访问数据库,可能会导致数据库的崩溃。

这些小概率事件是必须要规避的。冷门数据突然变成热点数据。

突发性热点缓存重建导致系统压力暴增问题分析

加锁。使用单例模式。双重检索机制。先查询缓存,没有;加锁,然后再查询缓存,如果没有就一个请求去查询数据库,后续请求都阻塞;当其执行完毕之后,后续再来线程再试一下就有数据返回了,不用继续执行后续操作。

但是这个还是有点问题,这个就在单节点中有用,如果每个服务器节点都自己构建,那么这样也不行,还有就是锁对象的问题,不能使用类锁等;

所以可以使用分布式锁解决这个问题。此时就重新构建一次。

基于DCL机制解决热点缓存并发重建问题实战

注意:锁的命名尽量要见名知意,不能随便进行简写,除非是项目或者公司有默认的简写值才行。

代码是编写完成功能之后,再去考虑进行优化。

使用DCL,先查缓存,如果没有;就加锁,加锁之后,再查缓存一次,如果没有再去查数据库。

Redis分布式锁解决缓存与数据库双写不一致问题实战

更新数据库和缓存不是原子性的,导致数据库和缓存的数据不一致。可能多个线程并发执行,一个线程执行时间太长,导致数据不一致。

如果是先写数据库,然后删除缓存,正常情况下是没有问题;但是如果中间卡顿了一下,就可能导致数据不一致。可以进一步优化使用延时双删,但是这个还不行,因为这个时间并不确定。

当然正常情况下是必须要考虑异常情况的。

所以可以使用分布式锁来实现这个功能。这是另外一个锁,锁名称要见名知意。

要解决这样的小概率情况必须要使用这样的代码,这样会导致代码量增大,会令代码变得复杂。这样会导致查询路径变得很深,但是这只是第一次会这样;工作中百分之九十以上得场景查询得都是热数据,所以后续的请求很早就返回数据了。使用大量的代码是解决小概率事件的。然后绝大部分请求不会一直走全部的代码。

优化方案:

很多情况下都是读多写少的情况。这样的情况可以使用读写锁。读读共享,并发量升高;读写,写写是互斥要加锁的。只有写的时候才会有不一致的情况发生。

读写锁在redisson中也是通过lua脚本来实现的,加锁的时候有一个标记,mode标识,是读还是写。读的时候类似重入锁,可以并发读。解锁的时候就是重入次数减一,直到减到0.

写的时候是互斥的。锁一定要是同一个。

加锁时先判断是读锁还是写锁,读读共享;读写就阻塞等待等。如果先是写锁,后续所有的线程都要进行等待。

 

如果是有读还有写,那么使用这个读写锁就不太合适了。具体场景具体分析。针对数据库和缓存来说,可以加读写锁。多个线程并发执行才有并发安全的问题。

大促压力暴增导致分布式锁串行争用问题优化实战

还有就是多次高并发查询,如果是有上万的请求来,请求的步骤都一样,查询缓存么有值;然后就是加锁,然后再查缓存,有了值就返回,并且解锁。这样加锁和解锁也是比较耗时的。所以还是可以优化的,如果可以确认代码可以再1秒中执行完毕,或者是百分之九十九点九,就可以使用tryLock,这个加上一个过期时间,如果时间到了,就直接不等待了,直接去访问缓存。但是如果1秒无法执行完成,那么就出现bug。

这个就是权衡。这就是架构思维。

一次微博明星热点事件导致系统崩溃原因分析

缓存雪崩,刚开始缓存少量失效,但是如果请求量越来越大,那么会导致错误放大,最终可能会导致系统崩溃;请求是越来越多,会导致连接没空余的,别的功能访问就受阻,可能最后导致崩溃。

此时可以进行限流,前端进行了限流,后端也进行限流。

利用多级缓存架构解决Redis线上集群缓存雪崩问题

此时可以使用多级缓存,加上一个JVM级别的缓存。

但是这个也是有问题的,热点数据是变化的,这个要考虑;还有就是如果不同的节点数据更新,可能会导致不同节点JVM缓存数据不一致,这个也是要避免的。

使用zk,或者MQ也是可以的,当一个节点的数据发生变化,发出消息,令别的节点订阅,进行修改;此时会有短时不一致的情况,此时就不要去考虑绝对一致性了,这样就太复杂了,有些过度设计了。只要不是长时间不一致就是可以接受的。zk也不能绝对一致。

正常来说是不会这么做的,因为增删改查是很频繁的,如果这样就会导致消息太多;不便维护;

可以再进行拆分,抽取出来一个热点缓存,监听所有的请求,进行计算,判断哪些是热点缓存,保证热点缓存的值保存在缓存中。可以使用实时计算。

posted @ 2024-05-03 18:52  圣辉  阅读(2)  评论(0编辑  收藏  举报