程序员的公众号:源1024,获取更多资料,无加密无套路!
最近整理了一份大厂面试资料《史上最全大厂面试题》,Springboot、微服务、算法、数据结构、Zookeeper、Mybatis、Dubbo、linux、Kafka、Elasticsearch、数据库等等
获取方式: 关注公众号并回复 666 领取,更多内容持续奉上
缓存可以提升性能,减轻数据库压力,同时,也存在一些新的问题,如缓存和数据库之间的数据一致性问题。
-
先更新缓存,再更新数据库
问题:如果缓存更新成功,数据库更新失败,导致数据不一致
-
先更新数据库,再更新缓存
问题:如果数据库更新成功,更新缓存失败,导致数据不一致
-
先删除缓存,再更新数据库
问题:如果删除缓存成功,更新数据库失败,此时新的请求读取到数据库中的旧数据更新到缓存中,这样好像数据库与缓存中的数据是一致的。但是如果在高并发环境下,极端情况还是会导致数据不一致问题的(比如同时进来的两个请求,一个写请求,一个读请求,写请求删除缓存,并且成功更新主库的数据,但还没同步给从库,读请求就判断缓存为空,去从库里读取数据,拿到旧数据后写入缓存,随后写请求将新数据同步给从库,就导致了缓存和数据库不一致问题)
-
先更新数据库,再删除缓存
问题:更新数据库成功,删除缓存失败,导致数据不一致
解决方案:
- 延迟双删
延迟双删策略是分布式系统中数据库存储和缓存数据保持一致性的常用策略,但它不是强一致的。
实现:先删除缓存然后更新数据,在最后延迟 N 秒再去执行一次缓存删除(这里设置的N秒主要是保证读请求结束,写请求可以删除读请求造成的缓存脏数据,N需要根据实际情况评估);如果第二次缓存删除失败,可以考虑将需要删除的key发送给消息队列,通过消费重试,直到删除成功。
- MQ重试删除
更新完数据库之后进行删除,如果删除失败则向MQ发送一条消息,然后消费者不断进行删除尝试。
- binlog异步删除
实现:低耦合的解决方案是使用canal。更新数据库,会把操作信息记录在binlog日志中,canal监听主机mysql的二进制文件,当数据发生变化时发送给MQ,最终消费进行删除。
系列文章索引
MyBatis的插件能在哪些地方进行拦截?
了解MyBatis的缓存机制吗
面试官:谈谈对volatile的理解
Spring中用到了哪些设计模式
面试官:说一下SQL的执行过程
线程池的工作原理