Redis缓存不一致的问题(五)

缓存不一致的情况有两种:

  • Redis缓存中是旧值;
  • 数据库中值是旧值;

缓存一致性需要保证的是,当缓存中有值的时候,数据库的值必须与缓存一致。

根据是否接收写请求,可以将缓存分为读写缓存只读缓存。两种发生缓存不一致的情况不同,需要分开来应对。

在只读缓存中,新增数据会直接写到数据库中,不会操作缓存,所以不会出现缓存不一致。删改数据时,需要删除数据库和缓存中的数据,在删改数据库和缓存时,无论哪个先后,中间出现故障都会产生旧值,即缓存不一致的情况。

如何解决数据不一致

重试机制

可以将要删除的缓存值或者要更新的数据库值暂存在消息队列中。当应用没有能够成功删除缓存或者更新数据库值时,可以从消息队列中重新读取这些值,然后再次进行删除或更新。

如果能够成功地删除或更新,就需要将这些值从消息队列中去除,以免重复操作。如果重试超过一定次数,还是没有成功,就需要向业务层发送报错信息了。

但重试机制在并发量大时,依旧会有问题。要分先删缓存还是先更新数据库两种情况说说。

情况一:先删缓存,后更新数据库。

在并发的情况下,假设线程A先删除缓存,后更新数据库;那么在这期间线程b读取数据,发现缓存缺失,就会去数据库读取数据,那么就会产生两个问题:

  • 线程b读取到的旧数据;
  • 线程b读到旧数据后发现缓存缺失,那么就会去更新缓存,将缓存更新为了旧值,这样后面读取的线程访问的就是旧值,产生了数据不一致;

这样的情况可以采用延时双删的策略,即在线程A更新完数据库后,sleep一段时间,再删除缓存。这样做的目的是为了当线程b发现缓存缺失后将缓存更新了旧值,然后将这个旧值缓存给删除掉。

个人觉得这个策略并不是很好的做法。首先延时的时间不好确定,无法得知下一个读线程会更新缓存的时间。其二在并发量大的情况下,当线程a还没做延时双删时,会有大量的线程读取到缓存中的旧值。所以觉得这种方案只是会降低缓存不一致的概率,并非是"银弹。

情况二:先更新数据库值,再删除缓存值。

在并发的情况下,假设线程a先更新数据库,再删除缓存值。那么在更新数据库后删除缓存值前,会也线程读取到缓存中的旧值。不过由于删除缓存操作是内存操作,所以可以认为这一步是很快的,影响量不会很大。

不过对于正常业务来说,这种短时间内的数据不一致并不会影响很大。如果对于数据一致性要强要求的,要么不使用缓存,要么是利用分布式锁将请求变为串行。具体的做法得分场景选择了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值