Redis延时双删实现mysql和redis的数据一致性

在高并发的业务场景下,为了保护数据库,我们一般都会做缓冲。所以,假设我们用redis做一个缓冲操作,让请求先访问redis,而不是直接访问mysql,来缓解数据库的压力。

平常的读取缓存没啥问题,但假设涉及到更新数据,特别是需要更新数据库的同时更新缓存,就很容易出现数据库和缓存数据不一致的问题。
不管是先写入库在删除缓存,还是先删缓存再写入库,都有可能出现数据不一致的情况。
比如:
1.删除了缓存,还没来得及入库,另一个线程来读取,发现缓存为空,去数据库拿到的还是旧数据,然后再做缓存,此时缓存中就是脏数据。
2.先入库,再删除缓存前,另一个线程来读取,拿到的还是旧数据。

因为写和读是并发的,无法保证顺序,就很容易出现缓存和数据库数据不一致的问题,如何解决?

记录一下延时双删策略!

延时双删就是在写入数据库前后都进行redis.del操作,并做延时操作。具体步骤为:

1.先删除缓存。redis.del(key)。

2.写入数据库。db.insert/update。

3.休眠300毫秒。这个根据读取的业务时间来定。

4.再次删除缓存。redis.del(key)

在此基础上,缓存也要设置过期时间,来保证最终数据的一致性。
只要缓存过期,就去读数据库然后重新缓存。

这种双删+缓存超时的策略,最差的情况也是超时时间内数据不一致,而且写的时候增加了耗时。

但是还会出现一个问题,如何保证写入库厚,再次删除缓存成功?

如果删除失败,还有可能出现数据不一致的情况。这时候需要提供一个重试方案。

可以启动一个订阅程序订阅数据库的binlog,提取所需要的数据和key,另起代码获取这些信息。如果尝试删除缓存失败,就发送消息给消息队列,重新从消息队列获取数据,重试删除操作。

你可能感兴趣的:(redis,缓存,数据库)