今天,我将与您讨论如何分析数据库和缓存之间的双写一致性。很多人可能不太了解。为了让大家更好的了解,边肖为大家总结了以下内容。希望你能从这篇文章中有所收获。
缓存因其高并发性和高性能而被广泛应用于项目中。阅读过程如下:
双写一致性有以下三个要求:
缓存无法读取脏数据。
缓存可能会读取过时的数据,但最终的一致性应该在可容忍的时间内实现。
这个可容忍的时间越短越好。
为了同时满足上述三个要求,读请求和写请求可以序列化并串入内存队列,以确保不会出现不一致。但是序列化后,系统的吞吐量会大大降低,支持在线请求的机器会比正常多几倍。
因此,在这里,我们讨论三种常见的方法:
首先更新数据库,然后更新缓存
在更新数据库之前删除缓存。
首先更新数据库,然后删除缓存。
1. 先更新数据库,再更新缓存
这种方法普遍受到大家的反对,原因有以下两个:
原因一:线程安全角度。
如果同时请求A和请求B更新,将出现:
一个线程更新了数据库。
线程更新了数据库
线程更新了缓存
一个线程更新了缓存。
这说明请求A更新缓存应该早于请求B更新缓存,但是由于网络等原因,B比A更早更新缓存,这就导致数据脏了,所以不考虑。
同理,“先更新缓存,再更新数据库”的方案也会造成数据脏,所以不考虑。
2.原因:业务场景视角。
有以下两点:
如果您的业务需求中有更多的数据库写入场景和更少的数据读取场景,这种方案将导致在读取数据之前频繁更新缓存,从而浪费性能。
如果您写入数据库的值没有直接写入缓存,它们将在一系列复杂的计算后写入缓存。那么,每次写入数据库后,再次计算写缓存的值无疑是对性能的浪费。显然,删除缓存更合适。
如果必须更新缓存,请考虑将版本号添加到缓存的数据中。
2. 先删除缓存,再更新数据库
这个方案也会导致不一致。如果同时请求A和请求B更新,将出现:
请求写入和删除缓存
查询发现缓存不存在。
请求查询数据库以获取旧值。
将旧值写入缓存的请求
向数据库写入新值的请求。以上情况会导致不一致。此外,如果不采用为缓存设置到期时间的策略,数据将总是脏的。
解决方案:
请先删除缓存。
再次写入数据库(这两个步骤与之前相同)
休眠一定时间(如1秒或200毫秒),再次删除缓存。这样,可以再次删除缓存的脏数据。
然而,这种解决方案仍然会影响吞吐量,因为需要休眠线程。
3. 先更新数据库,再删除缓存
是很多项目采用的方案。让我们看看它是否安全。
假设有两个请求,一个用于查询操作,另一个用于b更新操作,将出现以下情况。
缓存刚刚失败。
查询数据库的请求,旧值
向数据库中写入新值的请求
删除缓存的请求
请求将找到的旧值写入缓存。
因此,产生了脏数据。然而,上述情况假设写请求比读数据库中的请求更快。事实上,在工程上,数据库的读操作比写操作快得多。
要么通过2PC或者Paxos协议保证一致性,要么想尽一切办法降低并发时脏数据的概率,可能是因为2PC太慢,Paxos太复杂。综合考虑,脸书选择了这第三种方案。
00-1010启动订阅程序,订阅数据库的binlog,获取需要操作的数据。在应用程序中,启动另一个程序从这个订阅程序获取信息并删除缓存。
看完以上内容,你对如何分析数据库和缓存的双写一致性有了更好的理解吗?如果您想了解更多知识或相关内容,请关注行业资讯频道,感谢您的支持。
内容来源网络,如有侵权,联系删除,本文地址:https://www.230890.com/zhan/129606.html