分布式-如何保证缓存与数据库的双写一致性

1. 双写一致性问题

分布式缓存涉及到缓存与数据库双存储双写,你只要是双写,就一定会有数据一致性的问题。

2. 双写一致性的要求

  • 缓存不能读到脏数据
  • 缓存可能会读到过期数据,但要在可容忍时间内实现最终一致
  • 这个可容忍时间尽可能的小

要想同时满足上面三条,可以采用读请求和写请求串行化,串到一个内存队列里去,这样就可以保证一定不会出现不一致的情况。但是,串行化之后,就会导致系统的吞吐量会大幅度的降低,要用比正常情况下多几倍的机器去支撑线上请求。

åå串è¡å

3. 更新策略导致的问题

(1)为什么不是更新缓存,而是删除缓存

  • 线程安全角度。同时有请求A和请求B,正常情况下A更新缓存应该比请求B更新缓存早才对,但是因为网络等原因,B却比A更早更新了缓存。这就导致了脏数据,因此不考虑;
  • 不是热点数据,只是频繁更新的场景,采用懒加载的思想,只有在使用到的时候才加载至缓存,不然浪费性能;
  • 压测一些写接口的时候,为了提高性能(吞吐量、QPS、TPS的概念形容,可以更专业一点),更新操作不会设置为更新缓存(项目内的操作记得没错的话,应该是先删除缓存,再将目前全部内容加载到缓存中),减少缓存频繁删除、加载的操作;

(2)先更新数据库,再删除缓存有什么问题

  • 假设一个请求A做查询操作,一个请求B做更新操作,那么会有如下情形产生:缓存刚好失效,A请求查询数据库,得到旧值;B请求更新数据库,并更新缓存,然后A请求再更新缓存。这样,脏数据就产生了,然而上面的情况是假设在数据库写请求比读请求还要快。实际上,工程中数据库的读操作的速度远快于写操作的。要么通过2PC或是Paxos协议保证一致性,要么就是想尽办法降低并发时脏数据的概率,大概是因为2PC太慢,而Paxos又太复杂,综合考虑,Facebook选择了这个第三种方案;
  • 假设同时请求A和请求B,请求A更新完数据库,未删除缓存,但是请求B查询读到的是旧的缓存数据怎么办;
  • 如果先修改数据库,再删除缓存。如果删除缓存失败了,那么会导致数据库中是新数据,缓存中是旧数据,数据就出现了不一致;

 

如果删除缓存失败,是否可以通过异常捕获等措施进行补偿,保持最终的数据一致性?

(3)先删除缓存,再更新数据库还有什么问题

数据发生了变更,先删除了缓存,然后要去修改数据库,此时还没修改。一个请求过来,去读缓存,发现缓存空了,去查询数据库,查到了修改前的旧数据,放到了缓存中。随后数据变更的程序完成了数据库的修改。数据库和缓存中的数据又发生了不一致问题。

只有在对一个数据在并发的进行读写的时候,才可能会出现这种问题。其实如果说你的并发量很低的话,特别是读并发很低,每天访问量就 1 万次,那么很少的情况下,会出现刚才描述的那种不一致的场景。但是问题是,如果每天的是上亿的流量,每秒并发读是几万,每秒只要有数据更新的请求,就可能会出现上述的数据库+缓存不一致的情况。

3. 定论 + 选择

  • 读的时候,先读缓存,缓存没有的话,就读数据库,然后取出数据后放入缓存,同时返回响应;
  • 更新的时候,先更新数据库,然后再删除缓存(不管先删除缓存还是先更新数据库,都存在一定时间的脏数据,虽然facebook选择先删除缓存,但是删除缓存然后还没更新数据库,如果立马有请求读取数据库,又重新加载旧数据到缓存,如果设置缓存时间过长或者永久,问题就很大,只能被动删除缓存,所以应该有其他辅助操作;如果是先更新数据库,再删除缓存,那么脏数据存在的时间应该是可接受的);
  • 为了避免删除缓存失败,可以使用一些重试机制,如MQ。为了与项目解耦,可以是使用阿里cancle订阅数据库binlog操作;

(a)更新数据库数据;

(b)数据库会将操作信息写入binlog日志当中;

(c)订阅程序提取出所需要的数据以及key;

(d)另起一段非业务代码,获得该信息;

(e)尝试删除缓存操作,发现删除失败;

(f)将这些信息发送至消息队列;

(g)重新从消息队列中获得该数据,重试操作;

参考资料:

如何保证缓存与数据库的双写一致性?

浅析数据库与缓存的双写一致性问题

分布式之数据库和缓存双写一致性方案解析(双删延时+异步消息)

Scaling Memcache At Facebook

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值