缓存一致性问题

缓存更新策略

被动更新: 设置key过期的时间,让其自动失效。
主动更新: 更新DB的时候,同时更新缓存
一般业务都是主动更新和被动更新结合使用。

缓存更新实现

  1. 调用者调用。失败重试3次,再失败,扔给消息队列异步处理。消息队列从数据库取最新的更新,保证成功
  2. DB中间件监听DB变化,更新缓存
利用DB中间件监听DB变化(比如阿里的Canal中间件,点评的Puma),从而对缓存进行更新。
这种办法的一个好处就是:把缓存的更新逻辑,和业务逻辑解藕。业务只更新DB,缓存的更新被放在另外一个专门的系统里面
主动更新 问题
存在一个问题:你是先更新缓存,后更新DB;还是反过来?
下面分别分析以下2个场景,假设有2个线程,t1, t2:
(1) 先更新缓存,后更新DB。假设有如下的执行系列:

t1更新缓存;
t2读缓存,因为t1把缓存更新了,导致t2没读到。从db中读,然后更新缓存;
t1更新DB。

上述操作系列会导致缓存脏数据。
但是这个不更新 缓存再读都是错的。只有等到下次更新才行。
但是更新操作总是比读操作少

(2)先更新DB,后更新缓存。假设有如下操作序列:

t1更新DB;
t2更新DB;
t2更新缓存;
t1更新缓存。
  • 1 上述操作系列会导致缓存脏数据。 但是这个不更新 缓存再读都是错的。只有等到下次更新才行。 但是更新操作总是比读操作少
  • 2 这个出现的情况概率小点。同时更新可以加乐观锁 再加上缓存过期失效策略,只会有部分时间不一致
  • 一句话,无论谁先谁后,只要更新缓存和更新DB不是原子的,就可能导致不一致。只是从实际业务来讲,一般缓存也都是保持“最终一致性“,而不是和DB的强一致性。
  • 并且一般建议先更新DB,再更新缓存,优先保证DB数据正确。

强一致

锁/分布式锁

缓存穿透

某个key,先查cache没查到,再查db也没有查到。 这种key的存在,会导致cache一直没办法命中,压力一直打在db上面。如果访问很高频,可能会压垮DB。

解决

- 当查询DB没查到时,往缓存中写入一个空值(缺省值),这样第2次再查,就不会打到DB上了。

缓存雪崩

缓存机器挂了,保证缓存的可用性 解决

  • 应用内也保持应用内缓存
  • 提高缓存的HA。比如缓存的主从复制。
  • 对DB的访问实行限流、降级

缓存并发

缓存过期后将尝试从后端数据库获取数据,这是一个看似合理的流程。但是,在高并发场景下,有可能多个请求并发的去从数据库获取数据, 对后端数据库造成极大的冲击,甚至导致 “雪崩”现象。此外,当某个缓存key在被更新时,同时也可能被大量请求在获取,

  • 解决 :锁/分布式锁 重试解决
类似“锁”的机制,在缓存更新或者过期的情况下,
先尝试获取到锁,当更新或者从数据库获取完成后再释放锁,其他的请求只需要牺牲一定的等待时间,即可直接从缓存中继续获取数据。

其他方法 不建议

由于数据库层面的读写并发,引发的数据库与缓存数据不一致的问题(本质是后发生的读请求先返回了),可能通过两个小的改动解决:
(1)修改服务Service连接池,id取模选取服务连接,能够保证同一个数据的读写都落在同一个后端服务上
(2)修改数据库DB连接池,id取模选取DB连接,能够保证同一个数据的读写在数据库层面是串行的

原文地址:https://www.cnblogs.com/clds/p/9122930.html

时间: 2024-11-03 03:38:02

缓存一致性问题的相关文章

缓存一致性和跨服务器查询的数据异构解决方案canal

当你的项目数据量上去了之后,通常会遇到两种情况,第一种情况应是最大可能的使用cache来对抗上层的高并发,第二种情况同样也是需要使用分库 分表对抗上层的高并发...逼逼逼起来容易,做起来并不那么乐观,由此引入的问题,不见得你有好的解决方案,下面就具体分享下. 一:尽可能的使用Cache 比如在我们的千人千面系统中,会针对商品,订单等维度为某一个商家店铺自动化建立大约400个数据模型,然后买家在淘宝下订单之后,淘宝会将订单推 送过来,订单会在400个模型中兜一圈,从而推送更贴切符合该买家行为习惯的

缓存一致性协议

刚看到一篇很好的介绍缓存一致性的文章,晚一点把其中的英文部分翻译过来 https://zhuanlan.zhihu.com/p/25876351 https://en.wikipedia.org/wiki/MESI_protocol

数据异构解决方案缓存一致性和跨服务器查询

缓存一致性和跨服务器查询的数据异构解决方案canal 当你的项目数据量上去了之后,通常会遇到两种情况,第一种情况应是最大可能的使用cache来对抗上层的高并发,第二种情况同样也是需要使用分库 分表对抗上层的高并发...逼逼逼起来容易,做起来并不那么乐观,由此引入的问题,不见得你有好的解决方案,下面就具体分享下. 一:尽可能的使用Cache 比如在我们的千人千面系统中,会针对商品,订单等维度为某一个商家店铺自动化建立大约400个数据模型,然后买家在淘宝下订单之后,淘宝会将订单推 送过来,订单会在4

zt:缓存一致性(Cache Coherency)入门 cach coherency

http://www.infoq.com/cn/articles/cache-coherency-primer http://www.cnblogs.com/xybaby/p/6641928.html 本文是RAD Game Tools程序员Fabian “ryg” Giesen在其博客上发表的<Cache coherency primer>一文的翻译,经作者许可分享至InfoQ中文站.该系列共有两篇,本文系第一篇. 我计划写一些关于多核场景下数据组织的文章.写了第一篇,但我很快意识到有大量的

分布式理论(4):Leases 一种解决分布式缓存一致性的高效容错机制(转)

作者:Cary G.Gray and David R. Cheriton 1989 译者:[email protected] 2011-5-7 出处:http://duanple.blog.163.com/blog/static/70971767201141111440789/ [ 序:所谓租约(leases),其实就是一个合同,即服务端给予客户端在一定期限内可以控制修改操作的权力.如果服务端要修改数据,首先要征求拥有这块数据的租约的客户端的同意,之后才可以修改.客户端从服务端读取数据时往往就同

由一个bug引发的SQLite缓存一致性探索

问题 我们在生产环境中使用SQLite时中发现建表报“table xxx already exists”错误,但DB文件中并没有该表.后面才发现这个是SQLite在实现过程中的一个bug,而这个bug与数据字典的一致性相关,下面这篇文章主要讨论SQLite的缓存机制,以及缓存一致性实现的策略,希望对大家了解SQLite缓存机制有一定的帮助. 缓存 SQLite中缓存主要包括两方面,数据字典缓存和数据页缓存.SQLite本身是一个文件数据库,所有的数据都在一个DB文件中,文件以块(page)的形式

Java的多线程机制:缓存一致性和CAS

Java的多线程机制:缓存一致性和CAS 一.总线锁定和缓存一致性 这是两个操作系统层面的概念.随着多核时代的到来,并发操作已经成了很正常的现象,操作系统必须要有一些机制和原语,以保证某些基本操作的原子性,比如处理器需要保证读一个字节或写一个字节是原子的,那么它是如何实现的呢?有两种机制:总线锁定和缓存一致性. 我们知道,CPU和物理内存之间的通信速度远慢于CPU的处理速度,所以CPU有自己的内部缓存,根据一些规则将内存中的数据读取到内部缓存中来,以加快频繁读取的速度.我们假设在一台PC上只有一

多线程之:MESI-CPU缓存一致性协议

MESI(Modified Exclusive Shared Or Invalid)(也称为伊利诺斯协议,是因为该协议由伊利诺斯州立大学提出)是一种广泛使用的支持写回策略的缓存一致性协议,该协议被应用在Intel奔腾系列的CPU中,详见“support the more efficient write-back cache in addition to the write-through cache previously used by the Intel 486 processor” MESI

缓存一致性

多核处理器的基本架构 缓存(Cache) 本文是关于CPU缓存的快速入门.我假设你已经有了基本概念,但你可能不熟悉其中的一些细节.(如果你已经熟悉了,你可以忽略这部分.) 在现代的CPU(大多数)上,所有的内存访问都需要通过层层的缓存来进行.也有些例外,比如,对映射成内存地址的I/O口.写合并(Write-combined)内存,这些访问至少会绕开这个流程的一部分.但这两者都是罕见的场景(意味着绝大多数的用户态代码都不会遇到这两种情况),所以在本文中,我将忽略这两者. CPU的读/写(以及取指令

聊聊高并发(五)理解缓存一致性协议以及对并发编程的影响

Java作为一个跨平台的语言,它的实现要面对不同的底层硬件系统,设计一个中间层模型来屏蔽底层的硬件差异,给上层的开发者一个一致的使用接口.Java内存模型就是这样一个中间层的模型,它为程序员屏蔽了底层的硬件实现细节,支持大部分的主流硬件平台.要理解Java内存模型以及一些处理高并发的技术手段,理解一些基本的硬件知识是必须的.这篇会说一下跟并发编程相关的一些硬件知识. 一个基本的CPU执行计算的过程如下: 1. 程序以及数据被加载到主内存 2. 指令和数据被加载到CPU的高速缓存 3. CPU执行