最近的一次面试被问道了,一个经典题目:即缓存(redis)db的双写一致性.
之前没有仔细思考过,当时回答的不好.结束会整体思考了一下,这里做个总结.
坏在那里?
没有明确的场景,没有告知需要怎样的一致性.
一点思考
缓存一般的作用都是加速读的,所以在要求不高的情况加,我们只要保证让新请求最大概率读到新值即可.(失效==删除)
1.弱一致性
先写db再删缓存.有问题的case:读写并发的情况读先进入db获取了旧的值,写后进入db更新值.出db时写先出,删除缓存,读后出db将旧值放入缓存.因为一般情况下读请求都比写请求快,所以这是一种概率非常小的情况.
2.读写的原子性
加redis锁,将并发变串行.但是只能保证双写的原子性,不能保证其中任意写会不会失败导致不一致.
3.强一致性
使用分布式事务,保证双写要么都成功,要么都失败.但是不能保证网络延迟导致的时序问题.比如请求的时序是a,b 但是由于网络问题到达服务器的顺序变成了b,a.那么最终值就变成了a.解决方案.带上一次的值或者版本号(乐观锁的解决方案).
4.线性一致性
使用raft服务保证请求的时序顺序,分布式事务保证双写的一致性.
end
这样我们我们就根据一致性强度要求的不同完整的讲述了这个问题的解决方案.
网友评论