场景是这样的: 一主二从,用户更改数据,先淘汰缓存,再往主库写数据(缓存的数据需要经过业务计算,所以不能直接更新缓存),此时用户读数据,这个读操作也许发生在写数据成功之前,也许发生在主从同步成功之前,总之读了脏数据写到缓存里,怎么办?
1
xing393939 2016-03-22 14:58:06 +08:00
“缓存的数据需要经过业务计算,所以不能直接更新缓存”
认为应该直接更新缓存,计算就计算呗 |
2
jasontse 2016-03-22 15:00:50 +08:00 via iPad
先写数据后淘汰缓存?
|
3
UnisandK 2016-03-22 15:01:22 +08:00
锁表?
|
4
stackboom 2016-03-22 15:08:36 +08:00
淘汰缓存-》写数据-》更新缓存。 58 沈剑 写过缓存与数据库数据一致性的文章,可以看一下。
|
6
caoyue 2016-03-22 16:54:57 +08:00
如果需要主从架构下的强一致性,还要缓存实时更新,同时还考虑效率,那太难了~
这方面没什么经验,瞎扯一下=-= 如果发生在写数据成功之前,锁就好了吧 如果是主从同步延迟导致的脏数据,有点头疼,只能在修修补补了: 1. 要是严格要求强一致,用同步模式,完全同步成功了再返回可以解决,但是性能……银行这种倒是可以这么干 2. 如果短时间的缓存脏数据可接受,做个队列定时更新脏数据 3. 多主方案,根据 id 保证同一份数据的操作放在同一个服务上 4. 不要把这些放在主从架构上,在之上构建一个中间层 5. 强行把部分操作路由到主库——好吧这种感觉很奇怪 |
7
mhycy 2016-03-22 17:03:01 +08:00
同意楼上关于先写入后淘汰缓存的做法,不这么做的原因是什么?并发写入?
|
8
eightqueen OP |
9
mhycy 2016-03-22 19:01:39 +08:00
@eightqueen
反过来道理一样,缓存淘汰失败,写入成功那么缓存还是过期的 |
10
eightqueen OP @mhycy 你觉得两件事哪个失败的概率高?
|
11
mhycy 2016-03-22 20:42:20 +08:00
二次淘汰好了。。
|
12
calease 2016-03-23 00:04:11 +08:00
写入 DB 成功前缓存里的根本不是脏数据。
写入 DB 成功后缓存里的数据才是 dirty 需要 invalidate , 所以当然是写完淘汰。 至于淘汰失败,首先楼主多虑, 该成功的操作就是会成功, 失败了只有可能: 1.程序有 bug , 2.服务面临瘫痪。 再者缓存应该设 expire 所以就算操作失败也迟早会更新。 最后如果一定要操作成功, 最简单的方法就是 retry , 设置 retry 上限。 retry 上限到了就该发 email/IM 通知全体服务挂了。 |