Java教程

数据库和缓存数据双写一致性问题

本文主要是介绍数据库和缓存数据双写一致性问题,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

参考:https://blog.csdn.net/qq_33135813/article/details/91352093?utm_medium=distribute.wap_relevant.none-task-blog-2~default~baidujs_title~default-0.wap_blog_relevant_pic

https://blog.csdn.net/wenlin_xie/article/details/87652240

1、什么是缓存-数据库双写一致性问题?

应用设计中,如果为了提高查询性能,将一些数据库查询到的数据放入了缓存中,那么就会出现一种情况,更新数据库某些数据的时候,由于需要将缓存中的数据和数据库的数据做同步,那么高并发场景下,就会受到其他更新操作或者查询操作的影响。

2、使用到缓存的情况下,更新数据库的数据,数据库和缓存应该怎么更新?

正常情况,对于数据实时性要求不高的系统,可以设置缓存有效期,可以保证缓存数据最终的一致性。如果对数据实时性要求高,就需要选择更好的方案。如下:

如果选择了更新数据库然后更新缓存这种设计,就会导致每次更新库表都要去查询最新的数据然后更新到缓存,假如这条数据客户实际访问的很少,就会导致浪费资源;

所以一般我们可以进行优化,选择删除缓存,那么只有当客户第一次用到这条数据的时候才去数据库查询,后续查询都会先去缓存获取,未命中才去数据库获取;

3、先删除缓存,后更新数据库的方案:(先更新库,后删除缓存,如果第一步成功了,第二部失败了会导致两边数据不一致的情况)

理论上,如果删除缓存失败,那么数据库也不会去更新,可以保持两边数据一致;缓存删除成功,数据库更新失败,那么客户查询这条数据的时候会去数据库获取,然后更新缓存,两边数据可以保持一致;

缺陷:假如删除缓存成功了,但是还未更新数据库,这时线程切换,切换到另一个查询任务线程,查询会走到去数据库获取数据然后更新缓存,那么缓存保存的就是旧数据,再切换回去更新数据库,这时两边数据就不一致了。

解决“线程切换干扰更新”的方案:

a、双删除策略,删除缓存-更新数据库-等待几百ms再删除缓存;可以保证上面那种线程切换导致读取旧数据到缓存的情形下,将旧数据及时删除。

如果还担心第二次删除会失败,那就再给缓存设置有效期,保证数据最终一致性。

b、引入阻塞队列。更新时,利用这条数据的唯一标识,创建一个与之对应的任务队列,保存到Map<唯一标识id, Queue<String>>,更新完数据库和缓存后,移除队列的这个元素,后续有读操作的时候,利用唯一标识获取相应队列,然后判断队列内是否有其他操作,是的话进入队列等候,后续再来一个查询请求时,判断如果队列中已经存在一个相同的查询等待请求任务在等待了,就不需要进入队列,直接阻塞等待更新操作完成再往下走。

 

这篇关于数据库和缓存数据双写一致性问题的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!