ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

缓存一致性

2022-01-06 21:34:55  阅读:101  来源: 互联网

标签:缓存 数据库 加锁 一致性 服务器 数据


缓存数据的一致性

读所有的数据,首先去缓存中获取,缓存中没有就去读数据库,最后在缓存中放一份。如果该数据在数据库中发生改变,那么缓存里面的数据如何和数据库保持一致?解决这个问题,目前有两个用的非常多的场景:

  • 双写模式
  • 失效模式

双写模式

修改数据库的数据后再修改缓存中的数据

双写模式

但又引出了一个问题,那就是当有并发时,线程一将数据库的值改为「一号」然后立刻将这个值保存到缓存,而保存过程中遇到了种种原因,如网络波动,导致了数据延迟抵达缓存服务器,而此时线程二已经将数据库数据改为「二号」然后将数据保存到缓存,线程二网络通畅,很快就抵达缓存服务器先于线程一将数据保存到缓存中,而此时线程一的数据才抵达缓存服务器,将数据「一号」保存到了缓存中(把二号覆盖),这时缓存中保存的就是一个脏数据。

脏数据被保存原理图

这是临时性的脏数据问题,但是在数据稳定、缓存过期后,又能得到最新的正确数据。

读到的最新数据有延迟,这就导致了数据的最终一致性问题。

失效模式

在改完数据库后,将缓存中的数据删除,下一次请求进来从缓存获取数据时发现没有对应数据,他会到数据库中查询并将数据保存在缓存中。

失效模式

失效模式也有数据最终一致性问题,例如有三台服务器同时并发,服务器一负载小,修改数据库和删除缓存一气呵成,服务器二负载大,在修改数据库时磨磨蹭蹭耗时很久,而服务器三是获取数据的,他读取缓存没有数据又去数据库中将数据查出来了,此时查询的是服务器一修改的数据。完成这些操作后服务器二才将数据库修改瞬间删除缓存,而服务器三在更新缓存时遇到网络波动,非常久后才成功将数据保存到缓存中,但他保存的却是服务器一修改的旧数据

脏数据被保存原理图

加锁

以上两种模式遇到的问题(乱序)都可以通过加锁来解决,但是加锁后系统可能会变得笨重,所以,如果我们的数据经常修改,那么我们还需要将其放到缓存中咩?

如果数据经常修改,那么我们的锁会经常在,会导致整个系统非常缓慢,如果我们想要实时的读取,数据一致性要求非常高,那么这种情况还不如不加锁,直接访问数据库。

解决方案

  • 我们发现无论是双写模式还是失效模式,都会导致缓存的的不一致问题。即多个实例同时更新就会出现问题,应该怎么办?
    1. 如果是用户纬度数据(订单数据,用户数据),这种并发几率非常小,那么就不需要考虑这个问题,缓存数据加上过期时间,每隔一段时间触发读的主动更新即可。
    2. 如果是菜单,商品介绍等基础数据,也可以去使用 canal 订阅 binlog 的方式。
    3. 缓存数据 + 过期时间也足够解决大部分业务对于缓存的要求。
    4. 通过加锁保证并发读写,写写的时候按顺序排队,读读则无所谓。所以适合使用读写锁。(业务不关心脏数据,允许临时脏数据可忽略)。

总结

  • 我们能放入缓存的数据本就不应该是实时性、一致性要求超高的,所以缓存数据的时候加上过期时间,保证每天拿到当前最新数据即可。
  • 我们不应该过度设计。增加系统的复杂性
  • 遇到实时性、一致性要求高的数据,就应该查数据库,即使慢点,也无所谓。

欢迎访问我的个人博客
博文在博客中的链接: https://www.ctong.top/index.php/archives/91

标签:缓存,数据库,加锁,一致性,服务器,数据
来源: https://www.cnblogs.com/CloverYou/p/15772970.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

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

ICode9版权所有