企业网站网页打开慢,wordpress图创,做视频网站视频放在哪里找,手机做网站用什么软件缓存可以提升性能#xff0c;减轻数据库压力#xff0c;在获取这部分好处的同时#xff0c;它却带来了一些新的问题#xff0c;缓存和数据库之间的数据一致性问题。
想必大家在工作中只要用了咱们缓存势必就会遇到过此类问题
首先我们来看看一致性#xff1a;
强一致性… 缓存可以提升性能减轻数据库压力在获取这部分好处的同时它却带来了一些新的问题缓存和数据库之间的数据一致性问题。
想必大家在工作中只要用了咱们缓存势必就会遇到过此类问题
首先我们来看看一致性
强一致性任何一次读都能读到某个数据的最近一次写的数据。弱一致性数据更新后如果能容忍后续的访问只能访问到部分或者全部访问不到则是弱一致性。
1.读取数据 当应用程序需要从数据库读取数据时先检查缓存数据是否命中。如果缓存未命中则查询数据库获取数据同时将数据写到缓存中以便后续读取相同数据会命中缓存最后再把数据返回给调用者。如果缓存命中直接返回。 单独的只读取数据场景是不会出现不一致。 只有读和写一起才会出现 那我们再来说下写数据的场景 问题如果数据库中的某条数据放入缓存后又马上被更新了那我们应该如何更新缓存
2.写数据
当我们对数据进行修改的时候到底是先删缓存还是先写数据库
先更新缓存再更新数据库先删除缓存再更新数据库先更新数据库再更新缓存先更新数据库再删除缓存 无非就是缓存用更新或用删除推荐直接删除 为什么不更新而直接删 因为缓存的更新成本更高因为你写入数据库的值很多情况并不是直接写入缓存的而是要经过一系列复杂的计算再写入缓存。那么每次写入数据库后都再次计算写入缓存的值无疑是浪费性能的。显然删除缓存更为适合。删除缓存操作简单副作用只是增加了一次 chache miss建议大家使用该策略。 先操作数据库还是先操作缓存 2.先操作缓存
2.1先更新缓存再更新数据库 缺点如果先更新缓存成功在更新数据库的时候失败这时候会导致数据不一致缓存的作用是不是临时将我们数据保存在内存便于提高查询速度但是如果某条数据在数据库中都不存在缓存这种数据没有一点意义
2.2.先删除缓存再更新数据库 缺点高并发场景下如果多个线程同时执行更新数据库再写缓存操作可能会出现数据库是新值而缓存中是旧值 2.3.先删缓存再删数据库 先删缓存再删数据库在多线程环境下当一个线程把缓存删掉之后另一个线程读缓存读不到缓存就会直接读库读到数据后就会更新缓存先前的线程呢才更新数据库会造成缓存脏读的情况很容易产生缓存脏读。
而且如果不采用给缓存设置过期时间策略该数据永远都是脏数据。
3.先操作数据库
3.1.先更新数据库再更新缓存 优点可以解决先更新缓存再更新数据库带来的假数据问题
缺点高并发场景下如果多个线程同时执行更新数据库再写缓存操作可能会出现数据库是新值而缓存中是旧值 3.2.先更新数据库再删除缓存 在高可用的系统系统里面我们追求数据最终一致性的话我们可以考虑先更新数据库再去删除缓存 也算是常用的方案这里介绍一下这个叫 Cache Aside Pattern。如果先更新数据库再删除缓存那么就会出现更新数据库之前有瞬间数据不是很及时。 同时如果在更新之前缓存刚好失效了读客户端有可能读到旧值然后在写客户端删除结束后再次设置了旧值非常巧合的情况。 有 2 个前提条件缓存在写之前的时候失效同时在写客户度删除操作结束后放置旧数据 — 也就是读比写慢。设置有的写操作还会锁表。
这个很难出现但是如果出现了怎么办使用双删 3.3先删数据库再删缓存 先删数据库再删缓存在多线程情况下当一个线程删除数据库另一个线程读取缓存数据读到的是缓存的数据当先前一个线程删完数据库后就会更新缓存这是缓存就正常了产生了一次脏读。
5.解决
5.1.强一致性
在强一致性系统中通过2PC、Paxos或分布式锁保持一致性可能会成为影响系统吞吐量、响应时间和可伸缩性的昂贵开销 因此通常采用一种相当宽松的一致性方法称为最终一致性。
5.2.最终一致性延时双删 关键间隔一段时间再删除是为了保证并发读请求写入的旧值最终能够被第二次删除删除掉
缺点延时双删可能对我们性能要求方面不能有太高的要求 注意我们需要自行评估项目的读数据业务逻辑的耗时即线程二从数据库读取数据 写入缓存完成 防止线程二覆盖掉新数据 如果第二次删除缓存失败怎么办?
4.为了防止删除缓存失败可以进行重试机制
同步重试如果并发量高的时候可能会影响接口性能异步重试 创建单独的一个线程进行重试但是在高并发的场景下可能会因为创建线程太多导致OOM交给线程池处理但是如果服务重启会导致数据丢失重试数据写入表通过定时任务重试可以保证数据不丢失但是对于实时性要求较高的该场景不太适用利用MQ消息中间件进行重试在消费者中处理 订阅mysql的binlong在订阅者中如果发现更新数据请求则删除响应的缓存比如使用canal中间件为了保证删除缓存成功可以增加MQ 6.总结
缓存策略的最佳实践是 **Cache Aside Pattern。**分别分为读缓存最佳实践和写缓存最佳实践。
读缓存最佳实践先读缓存命中则返回未命中则查询数据库再写到数据库。
写缓存最佳实践
先写数据库再操作缓存直接删除缓存而不是修改因为缓存的更新成本很高删除缓存操作简单副作用只是增加了一次 chache miss建议大家使用该策略。
在以上最佳实践下为了尽可能保证缓存与数据库的一致性我们可以采用延迟双删。
防止删除失败我们采用异步重试机制保证能正确删除异步机制我们可以发送删除消息到 mq 消息中间件或者利用 canal 订阅 MySQL binlog 日志监听写请求删除对应缓存。
那么如果我非要保证绝对一致性怎么办先给出结论
没有办法做到绝对的一致性这是由 CAP 理论决定的缓存系统适用的场景就是非强一致性的场景所以它属于 CAP 中的 AP。
所以我们得委曲求全可以去做到 BASE 理论中说的最终一致性。
其实一旦在方案中使用了缓存那往往也就意味着我们放弃了数据的强一致性但这也意味着我们的系统在性能上能够得到一些提升。