存储与数据库 | 青训营笔记

80 阅读4分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 4 天

上节课在掘金内部课程vip的字节跳动课程学习的存储与数据库。其中的redis让我影响极其深刻,我之前之知道redis缓存热点数据的用法直接用,但发现他缓存热点数据也有非常多细节,要考虑到很多东西,下面是我总结的笔记。

缓存穿透 

1、是什么 

缓存穿透是指客户端请求的数据在缓存和数据库都没有,这样缓存永远不会生效,这些请求都会打到数据库。

2、解决方案 

(1)缓存空对象

第一次他随便乱打个没有的id来查询缓存和数据库,我们就会返回null,然后把null也存到缓存中。 这样再他下一次带这个id来请求的时候,就会从缓存中拿到null。 

优点:简单实现,维护方便 

缺点: 额外的内存消耗,缓存了很多没用的数据(可以通过设置时间来缓解) 可能造成短期的不一致。因为是随便乱打的id发的请求,我们帮这个id存缓存了,以后要是真的有这个id了,到时候拿这个id来查也是null(也是控制缓存的时间来缓解,也可以当我们新增数据的时候,主动插入缓存替换掉null) 

(2)布隆过滤器

在请求到缓存前加层布隆过滤器,如果这个数据存不存在,直接拒绝,不给继续请求。 布隆过滤器是怎么知道在不在呢? 是通过hash算法算出哈希值,将这些哈希值换成2进制位保存到布隆过滤器,判断数据是否存在的时候就判断对应的位置是0还是1。这种统计不是百分百准确 不存在的时候百分百不存在,说存在不一定存在,可以起到一定过滤作用。还是有一定击穿风险

优点:内存占用少,没有存多余的key 

缺点:实现复杂,存在误判的可能。 

(3)其他策略 

做好数据的基础格式校验 增强id复杂度,避免被猜测id的规律 加强用户权限校验 做好热点参数的限流

缓存雪崩 

1、是什么 

缓存雪崩是指同一时段大量的缓存key同时失效或redis服务宕机,导致大量请求打崩数据库 

2、解决方案 

给不同的key的TTL(过期时间)添加随机值(可以设置成30分钟到40分钟之间的随机数) 利用Redis集群提高服务器的可用性(哨兵机制) 给缓存业务添加降级限流策略(比如当服务器出现问题的时候,拒绝服务,牺牲部分服务来保证安全) 给业务添加多级缓存(nginx、redis、jvm都可以添加缓存,最后才到数据库)

缓存击穿 

1、是什么 

缓存击穿问题也叫热点Key问题,就是一个被高并发访问并且缓存重建业务较复杂的Key突然失效了,无数请求访问会瞬间给数据库带来巨大冲击。 高并发访问可以理解为做活动的商品,同一时间有无数的请求来访问这个商品。 缓存重建比较复杂就是缓存可能会过期失效,失效的时候重新添加到缓存的时间很久(可能业务非常复杂,要多表查询运算才能得到的结果) 

 2、解决方案 

互斥锁

如果查到缓存中没有,就加锁查数据库冲击,写入缓存之后再释放锁。这个期间内,所有访问的请求都没有拿到锁只能等待重试,直到缓存更新完毕读取缓存。 

 优点:没有额外的内存消耗、保证缓存和数据库一致性,实现简单 

 缺点:线程需要等待,性能受影响用户体验不好。可能有死锁的风险 

逻辑过期

设置缓存过期时间的时候,不是真正的设置,而是设置在value里面,如果查询缓存发现逻辑删除时间过期了,就new一个新的线程加锁来查询数据库更新缓存,更新完毕后才释放锁,自己返回旧数据。这个期间内其他线程都没有拿到锁,都返回旧数据,直到更新完毕 

 优点:线程不用等待,性能好。 

 缺点:不保证一致性,有额外内存消耗,实现复杂。

总结

我们在使用redis的时候一定要注意到这些问题,非常关键,当我们平时使用缓存一般的正常数据的时候,一般就考虑缓存穿透就行了。如果我们要缓存热点数据的时候,我们就得考虑到缓存击穿,有可能数据量非常庞大会瞬间打爆数据库,而且我们需要提前进行预热。