缓存与数据库的双写一致性 | Consistency between redis cache and sql database #54
Replies: 74 comments 32 replies
-
不管是何总方案,归根到底是强一致性和最终一致性,搞明白这两种的区别即可。强一致性必须保证全局事务,更新时任何读操作都是锁住的;最终一致性,在读的过程中会有短暂的数据不一致,但是任何写操作情况下也必须加全局事务锁或者采用补偿式去补偿不一致带来的后果。(读写操作,都是针对有业务关联的数据) |
Beta Was this translation helpful? Give feedback.
-
'你好。已收到你的邮件,我会在假期结束后尽快处理。————————————这是来自QQ邮箱的自动回复邮件。'
|
Beta Was this translation helpful? Give feedback.
-
这是来自QQ邮箱的假期自动回复邮件。
您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。
|
Beta Was this translation helpful? Give feedback.
-
您的邮件我已收到!我会尽快回复您的!!!
|
Beta Was this translation helpful? Give feedback.
-
您好,我将尽快给您回复。
|
Beta Was this translation helpful? Give feedback.
-
这是来自QQ邮箱的假期自动回复邮件。您好,~您的邮件我已收到,谢谢!
|
Beta Was this translation helpful? Give feedback.
-
'你好。已收到你的邮件,我会在假期结束后尽快处理。————————————这是来自QQ邮箱的自动回复邮件。'
|
Beta Was this translation helpful? Give feedback.
-
这是来自QQ邮箱的假期自动回复邮件。
您好,我最近正在休假中,无法亲自回复您的邮件。我将在假期结束后,尽快给您回复。
|
Beta Was this translation helpful? Give feedback.
-
您的邮件我已收到!我会尽快回复您的!!!
|
Beta Was this translation helpful? Give feedback.
-
这是来自QQ邮箱的假期自动回复邮件。
您好,邮件已收到。我将尽快给您回复。谢谢
|
Beta Was this translation helpful? Give feedback.
-
您好,我将尽快给您回复。
|
Beta Was this translation helpful? Give feedback.
-
这是来自QQ邮箱的假期自动回复邮件。您好,~您的邮件我已收到,谢谢!
|
Beta Was this translation helpful? Give feedback.
-
个人记录一下 其次,我觉得这个问题主要聚焦在删除缓存之后到将更新数据库放到队列之前存在一个空档期,这个空档期在高并发的情况下,有可能被其他线程给钻进来,那么我们只需要聚焦于这个空档期就行了! 个人思考的解决方案:
这个思路的缺点就是sleep这段时间会返回老数据,但是sleep这段时间是无需加锁等其他操作的,对于并发而来请求,数据也是可以返回的! |
Beta Was this translation helpful? Give feedback.
-
保证了最终一致性,你要是要求强一致性,那在考虑别的方法
…------------------------------------------------------------------
发件人:geekhoon <notifications@github.com>
发送时间:2020年1月15日(星期三) 16:44
收件人:doocs/advanced-java <advanced-java@noreply.github.com>
抄 送:MissHuZeQuan <huzequan1109@dingtalk.com>; Comment <comment@noreply.github.com>
主 题:Re: [doocs/advanced-java] 缓存与数据库的双写一致性 | Consistency between redis cache and sql database (#54)
看到各位回答很多人说:内存队列做串行化.可是这样就降低了效率.这里提供一个新思路就是.先更新数据库再删除缓存.之后使用MQ延迟队列(可以延迟个50-100毫秒)去做异步再删除.
首先我认为肯定要先删缓存,再更新数据库,这二者的顺序是不能换的,否则更新完成,缓存未删除,查到的数据那势必不一致。
使用MQ异步删除,并不能保证一致性
内存队列做串行化是考虑具体场景的,并不适用所有情况。有强一致性要求的才考虑这种做法。否则双删即可
对 这个是我说错了 要先删缓存,再更新数据库,这二者的顺序是不能换的.使用MQ做异步删除为什么能保证一致性呢 可以展开说一下嘛.
比如说你先删缓存,现在去修改数据库,修改的过程中有查询操作去查了数据库,又把旧数据添加到了缓存,你现在数据库更新完了,用mq去延迟删除缓存,那这个延迟期间,所有的查询查的还是旧数据
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub, or unsubscribe.
|
Beta Was this translation helpful? Give feedback.
-
比如说你先删缓存,现在去修改数据库,修改的过程中有查询操作去查了数据库,又把旧数据添加到了缓存,你现在数据库更新完了,用mq去延迟删除缓存,那这个延迟期间,所有的查询查的还是旧数据 |
Beta Was this translation helpful? Give feedback.
-
对 这个是我说错了 要先删缓存,再更新数据库,这二者的顺序是不能换的.使用MQ做异步删除为什么能保证一致性呢 可以展开说一下嘛. |
Beta Was this translation helpful? Give feedback.
-
首先我认为肯定要先删缓存,再更新数据库,这二者的顺序是不能换的,否则更新完成,缓存未删除,查到的数据那势必不一致。 |
Beta Was this translation helpful? Give feedback.
-
看到各位回答很多人说:内存队列做串行化.可是这样就降低了效率.这里提供一个新思路就是.先更新数据库再删除缓存.之后使用MQ延迟队列(可以延迟个50-100毫秒)去做异步再删除. |
Beta Was this translation helpful? Give feedback.
-
高并发下保证绝对的一致,就需要用到内存队列做异步串行化。非高并发场景,双删策略基本满足了。如果特别要求强一致性,并不适合放在redis |
Beta Was this translation helpful? Give feedback.
-
作者写的其实比较清楚了。 不管先删除缓存,还是先更新数据库,都会出现数据不一致问题,因为这本身就不是一个原子操作。只是作者提到,如果不在高并发的情况下,这种现象出现的可能性极低(但不代表不存在)。 其实原子操作相对于非原子操作来说,本来就是一个极其耗性能的东西,因为原子操作需要的是排他的串行操作,根据阿姆达尔定律就可以证明。 |
Beta Was this translation helpful? Give feedback.
-
个人觉得缓存双删比较简单靠谱,而且编码不是那么复杂 |
Beta Was this translation helpful? Give feedback.
-
所以作者说先删缓存,再更新数据,然后用内存队列保证串行化,等数据库更新完再去读库就没有这么多幺蛾子了。还有同学提到的用读写锁。读写锁底层用的AQS其实也是用内存队列做的,保证顺序 |
Beta Was this translation helpful? Give feedback.
-
不是读写分离数据库,悲观锁可以解决,但主从读写分离,就真不知怎么解决了,
… 先删除缓存,更新数据库,预计数据库更新需要时间t,然后在提交数据库更新t时间后再次删除缓存
|
Beta Was this translation helpful? Give feedback.
-
先删除缓存,更新数据库,预计数据库更新需要时间t,然后在提交数据库更新t时间后再次删除缓存 |
Beta Was this translation helpful? Give feedback.
-
更新前删缓存
更新后删缓存
这种应该会比较好一点~
|
Beta Was this translation helpful? Give feedback.
-
我怎么感觉先删除缓存,再更新数据库 和 先更新数据库再删除缓存是一样的都会有问题呢 |
Beta Was this translation helpful? Give feedback.
-
其实根据 《Cache-Aside pattern》先更新数据库再删缓存就可以啦 |
Beta Was this translation helpful? Give feedback.
-
双写一致性校验应该可以 |
Beta Was this translation helpful? Give feedback.
-
诚如文章所说 为避免数据不一致 给出的思路是:先删除缓存,再更新数据库
那么如果现在有两个线程 一个A更新 一个B读取,当A线程在更新的时候先把缓存给删掉了然后去做更新数据库的时候,B线程来读取数据的时候发现缓存没有数据(被A给删掉了)然后去读取数据库把数据读取出来放到了缓存中,这个时候A线程再去做更新数据库的操作...那么好戏来了...数据库和缓存真的不一致了. 请问要如何解决呢?
Beta Was this translation helpful? Give feedback.
All reactions