前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >缓存一致性

缓存一致性

作者头像
OPice
发布2020-02-10 11:43:39
9710
发布2020-02-10 11:43:39
举报
文章被收录于专栏:D·技术专栏D·技术专栏

  系统程序处理时,缓存作为DB的一道屏障,可以防止大量请求达到数据库,造成压力过大,还可以提高查询效率。

image.png

  • 问题 并发情况下,会导致数据不一致情况。缓存中和DB中的数据存在差异,原因是因为DB中数据发生变化,需要同步更新缓存中的数据,这时更新缓存数据有可能失败。
  • 解决方案
  1. 先更新缓存,后更新数据库 问题:两个更新线程更新同一条数据,A更新缓存,B更新缓存,B更新数据库,A更新数据库。显然缓存中的数据是脏数据。
  2. 先更新数据库,后更新缓存 问题:同样在两条更新线程中,出现顺序不一致,导致缓存中出现脏数据。
  3. 先更新数据库,后删除缓存 问题:1、更新数据后,在还没有删除缓存之前,有条读的线程,会导致读线程的数据为脏数据,但是后续的线程,读取缓存DB的新值。 2、缓存失效,A先读取DB值,B更新数据库,B删除缓存,A将旧值写入缓存中。
  4. 先删除缓存,后更新数据库 问题:A先删除缓存,B查询发现缓存失效,B缓存旧值,A更新数据库,缓存B的脏数据。
  • 结论 所以在并发情况下,操作数据库和缓存总会有顺序,一旦顺序不一致就会导致脏数据的情况。 1、缓存删除还是更新? 而且更新缓存会导致不必要的开销,比如更新一个库中的数据,但是缓存中是多个库中共同计算的结果,这是更新缓存就需要重新计算一遍。如果在查询不是很频繁的时候,这次计算是多余的。 2、先写库,还是先写缓存? 先删除缓存,后写库,这样就算后面写库失败了,缓存也是null,不会导致脏数据。如果先写库,后面更新缓存失败,缓存中的数据为脏数据。

如何解决先删缓存,后更新库带来的脏数据问题和缓存更新失败问题? 1、对数据库和缓存操作做同步,性能有损失。使用分布式锁 2、 双删,A更新数据库,A删除缓存,A.sleep(1000),A删除缓存

更新失败使用MQ来实现重试,订阅数据库binlog日志或者使用框架的拦截器订阅写操作。

Spring Cache

大概回顾一下Spring cache 的用法

  • @Cacheable 用于方法配置,根据方法参数对结果缓存

属性

解释

value

缓存的名称

key

缓存的key写法按照SpEL预发,默认使用方法名+参数组合

condition

缓存的条件,SpEl表达式

  • @CachePut 用于更新数据,每次都会执行,并将结果缓存
  • @CacheEvict 用于删除数据,将缓存数据删除 多了两个属性

属性

解释

allEntries

是否清空所有缓存,默认false

beforeInvocation

true:方法执行前删除,默认false方法执行后删除

  • @Caching 多个注解嵌套使用,例如
代码语言:javascript
复制
@Caching(put = {
@CachePut(value = "user", key = "#user.id"),
@CachePut(value = "user", key = "#user.name")
})
public User save(User user) {}

Spring默认是先写库,后写缓存,可以通过beforeInvocation指定。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Spring Cache
相关产品与服务
数据库
云数据库为企业提供了完善的关系型数据库、非关系型数据库、分析型数据库和数据库生态工具。您可以通过产品选择和组合搭建,轻松实现高可靠、高可用性、高性能等数据库需求。云数据库服务也可大幅减少您的运维工作量,更专注于业务发展,让企业一站式享受数据上云及分布式架构的技术红利!
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档