缓存设计——笔记

缓存设计时一般会遇到3个问题:

  1. 缓存实时性和一致性问题
    实时策略:这种策略实时性好,用户体验佳,默认使用。读取数据,应用程序先从缓存取数据,没有得到,则从DB中取数据,成功后,放到缓存中。如果命中,应用程序从缓存中取数据,取到后返回。那么为什么不直接更新缓存呢?因为多线程更新数据库的情况下,数据库可以保证事务,但是网络延迟或者线程调度更新缓存的时候,可能出现乱序。

异步策略:当请求穿透缓存,不先直接访问数据库,而是返回一个默认值,或者直接写入缓存一个默认值,然后往消息队列里面放入一个数据加载的事件,在背后有一个消费者进程,消费消息后,会异步的读取数据库,然后更新缓存。可以将多个队列中的任务合并请求,合并更新缓存,解耦实现了削峰填谷(消息中间件的作用),提高了效率。
那么老生常谈的问题来了,先更新数据库还是先更新缓存更好呢?那要根据具体业务场景来看(CAP只能要两个,看取舍)。
(1)先更新数据库,后异步更新缓存。当数据库更新后,同样生成一个异步消息,放入消息队列中,等待背后的任务通过消息进行缓存更新,同样可以实现消峰和任务合并。缺点就是实时性比较差,估计消息消费才能看到更新,好处是缓存数据持久性和缓存与DB一致性可以得到较大保证。可以结合使用阿里的canal,通过该框架模仿了mysql的slave数据库的备份请求,可以对MySQL的binlog进行订阅,分发到其他DB、消息中间件、ES、Hbase等等存储。

(2)先更新缓存,然后异步更新数据库。这种方式把缓存当成了数据库在用。所以这种情况适用于并发量大,但是数据没有那么关键的情况,优点是实时性好。
在实时策略扛不住大促的时候,可以根据场景,切换到上面的两种模式的一个,算是降级策略。
数据更新时候的缓存-DB不一致性
(1)先删除缓存,再更新数据库。这种策略是更新DB数据有时候会采用的方案,但是会很容易出现数据不一致。同时有一个请求A进行更新操作,另一个请求B进行查询操作。那么会出现如下情形:
1)请求A进行写操作,删除缓存;
2)请求B查询发现缓存不存在;
3)请求B去数据库查询得到旧值;
4)请求B将旧值写入缓存;(对于数据库来说,读比写要快,所以B先写缓存很正常)
5)请求A将新值写入数据库;
那么怎么办呢?更新数据库的写线程采用延时双删策略
1)先删除缓存;
2)再写数据库(这两步和原来一样);
3)休眠若干ms,再次删除缓存;(多少ms由读业务A的耗时决定,这样可以在读业务完成后,清空缓存中的脏值)
这样性能太差怎么办?改异步!可以将第2次删除改为异步操作(怕删除失败用消息队列,可以重试。简单点可以起其他线程或者进程执行即可),这样写请求的线程就不用阻塞了。

(2)先更新数据库,再删除缓存(为什么不直接更新缓存,上面“实时策略”有写到)
一般更倾向的方式,更不容易产生数据不一致。因为只有以下一种情况会导致不一致:
1)缓存刚好失效;
2)请求A查询数据库,得一个旧值;
3)请求B将新值写入数据库;
4)请求B删除缓存;
5)请求A将查到的旧值写入缓存;
但是这种情况的比要条件是:数据库“写操作”要比“读操作”更快,这个概率是极低的。
删除缓存失败怎么办? 引入消息队列,把要删除的缓存key存到消息队列,消费者重试删除。

  1. 缓存穿透问题
    原因:数据库确实没有这个key;内存不足LRU策略置换掉数据;冷数据;缓存失效
    解决方案:
    (1)同步访问数据库后更新,优点:实时性高 缺点:数据库压力大
    (2)异步访问数据库,先给前端一个默认的返回值(或者将这个默认值写入缓存,这样后面的并发请求也不会一起穿透),再将数据库请求提交到消息队列中,可以用消息key来区分是否是不同的请求,避免多个客户端的多次查询提交的多条消息,给数据库带来压力。缓存查到最新数据后触发一次前端的更新,显示最新结果。
  2. 缓存对数据库高并发访问
    解决缓存穿透问题基本能够避免数据库的超高并发,但是如果还吃不消,可以利用分布式锁,只允许一个相同请求访问数据库。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值