Join GitHub today
GitHub is home to over 50 million developers working together to host and review code, manage projects, and build software together.
Sign up缓存与数据库的双写一致性 | Consistency between redis cache and sql database #54
Comments
|
双写一致性校验应该可以 |
其实根据 《Cache-Aside pattern》先更新数据库再删缓存就可以啦 |
|
我怎么感觉先删除缓存,再更新数据库 和 先更新数据库再删除缓存是一样的都会有问题呢 |
|
更新前删缓存
更新后删缓存
这种应该会比较好一点~
bigzhan@126.com
发件人: wbliubin
发送时间: 2019-04-22 09:25
收件人: doocs/advanced-java
抄送: BigBlackSheep; Author
主题: Re: [doocs/advanced-java] 缓存与数据库的双写一致性 (#54)
我怎么感觉先删除缓存,再更新数据库 和 先更新数据库再删除缓存是一样的都会有问题呢
加入是先更新数据库再 删缓存,此时如果数据库还在更新中,一个线程进行了读取,不是也读取了脏数据了么
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub, or mute the thread.
|
|
先删除缓存,更新数据库,预计数据库更新需要时间t,然后在提交数据库更新t时间后再次删除缓存 |
|
不是读写分离数据库,悲观锁可以解决,但主从读写分离,就真不知怎么解决了,
发自我的 iPhone
在 2019年5月22日,12:00,joyway66 <notifications@github.com<mailto:notifications@github.com>> 写道:
先删除缓存,更新数据库,预计数据库更新需要时间t,然后在提交数据库更新t时间后再次删除缓存
—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub<#54?email_source=notifications&email_token=AG54C5AM5SHTJOT5CEJQUBDPWTAMJA5CNFSM4HDH4MQ2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGODV52PIA#issuecomment-494643104>, or mute the thread<https://github.com/notifications/unsubscribe-auth/AG54C5GW5WZXBKDEHL6JAN3PWTAMJANCNFSM4HDH4MQQ>.
|
|
所以作者说先删缓存,再更新数据,然后用内存队列保证串行化,等数据库更新完再去读库就没有这么多幺蛾子了。还有同学提到的用读写锁。读写锁底层用的AQS其实也是用内存队列做的,保证顺序 |
|
个人觉得缓存双删比较简单靠谱,而且编码不是那么复杂 |
|
作者写的其实比较清楚了。 不管先删除缓存,还是先更新数据库,都会出现数据不一致问题,因为这本身就不是一个原子操作。只是作者提到,如果不在高并发的情况下,这种现象出现的可能性极低(但不代表不存在)。 其实原子操作相对于非原子操作来说,本来就是一个极其耗性能的东西,因为原子操作需要的是排他的串行操作,根据阿姆达尔定律就可以证明。 |
|
高并发下保证绝对的一致,就需要用到内存队列做异步串行化。非高并发场景,双删策略基本满足了。如果特别要求强一致性,并不适合放在redis |
|
看到各位回答很多人说:内存队列做串行化.可是这样就降低了效率.这里提供一个新思路就是.先更新数据库再删除缓存.之后使用MQ延迟队列(可以延迟个50-100毫秒)去做异步再删除. |
首先我认为肯定要先删缓存,再更新数据库,这二者的顺序是不能换的,否则更新完成,缓存未删除,查到的数据那势必不一致。 |
对 这个是我说错了 要先删缓存,再更新数据库,这二者的顺序是不能换的.使用MQ做异步删除为什么能保证一致性呢 可以展开说一下嘛. |
比如说你先删缓存,现在去修改数据库,修改的过程中有查询操作去查了数据库,又把旧数据添加到了缓存,你现在数据库更新完了,用mq去延迟删除缓存,那这个延迟期间,所有的查询查的还是旧数据 |
|
保证了最终一致性,你要是要求强一致性,那在考虑别的方法
…------------------------------------------------------------------
发件人: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.
|
这个和保证最终一致性没有关系。这个方案是在非高并发的情况下,“赌”它不会出现不一致。如果“赌”失败了,就一定会不一致! |
|
请问一下各位,先更新数据库,再删除缓存。如果删除缓存失败了,那么会导致数据库中是新数据,缓存中是旧数据,数据就出现了不一致。什么情况下会出现删除缓存失败?如果是redis宕机,那程序会报错,事务会回滚;如果是删除错了缓存,那是代码的问题了,请不吝赐教 |
|
类似这种多个操作,又要原子保证的,是不是直接加redis锁就可以了呢? |
|
作者最后方案是放入队列,都放入队列,那怎么响应给客户端呢? |
|
如果是在读是高并发,而写是少量的情况下,删除更新数据库之后, |
redis是先把数据存缓存的,然后通过AOF一秒刷一次磁盘,如果这时候宕机会丢掉这一秒的数据。然后根据RDB+AOF恢复之后,数据自然是不一致的 |
|
感觉没有那么绝对最好的方案,适合自己项目的就行 |
|
更新的时候先更新数据库,再删除缓存,如果缓存删除失败直接报错回滚数据库更新最简单实现 |
先删除缓存,再更新数据库一样会遇到你这个问题,丢失的这一秒,有可能就会丢失你的删除操作把 |
redis宕机并不一定会报错. 比如说用的redis cluster, 发生了分裂, 你是分裂后连接到少的那部分redis机器. 你认为你删除了缓存,其实并没有. |
|
更新
更新完数据库之后还没来得及删除缓存,机子挂掉了怎么办? |
为什么不把删除缓存 放到更新数据的事务里面? |
那照你这么说,就算先删除缓存,再更新数据库也没有任何意义了。因为"你认为你删除了缓存,其实并没有" |
|
删除缓存的一瞬间,流量瞬间进来后,redis缓存已经失去了意义了吧。 强一致性,怎么可能实现呢? 我发现很多人面试官都说先删除缓存,然后请求来了发现没缓存,再读取数据库,再插入缓存? 那假如来了1000并发,1000个请求,都发现没有缓存,然后1000个请求,都去后台mysql了。难道再加个分布式锁吗?只有一个线程可以去后台? |
多个线程之间串行处理 |
在你说的情况下更新radis缓存时,如果更新缓存失败了,mysql中是新数据,radis是旧数据,数据不一致,这其实是先操作mysql后操作缓存的弊端(后删除缓存也一样)。 |
那你们继续用作者提供的这几种方式吧,目前我们用的不是。 |
|
不是应该不能删除缓存吗,如果是热点数据,不是会造成缓存击穿吗?还是把更新数据库和更新redis数据做成事务好一些 |
诚如文章所说 为避免数据不一致 给出的思路是:先删除缓存,再更新数据库
那么如果现在有两个线程 一个A更新 一个B读取,当A线程在更新的时候先把缓存给删掉了然后去做更新数据库的时候,B线程来读取数据的时候发现缓存没有数据(被A给删掉了)然后去读取数据库把数据读取出来放到了缓存中,这个时候A线程再去做更新数据库的操作...那么好戏来了...数据库和缓存真的不一致了. 请问要如何解决呢?