ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

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

2022-01-28 12:00:08  阅读:53  来源: 互联网

标签:缓存 删除 数据库 更新 查询 缓存数据 一致性 数据 双写


参考: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>>,更新完数据库和缓存后,移除队列的这个元素,后续有读操作的时候,利用唯一标识获取相应队列,然后判断队列内是否有其他操作,是的话进入队列等候,后续再来一个查询请求时,判断如果队列中已经存在一个相同的查询等待请求任务在等待了,就不需要进入队列,直接阻塞等待更新操作完成再往下走。

 

标签:缓存,删除,数据库,更新,查询,缓存数据,一致性,数据,双写
来源: https://www.cnblogs.com/dust-to-dust/p/15387166.html

专注分享技术,共同学习,共同进步。侵权联系[admin#icode9.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有