Redis和数据库一致性又称为“双写一致性”,在分布式系统中,由于多个节点之间的并发读写操作,可能导致数据不一致的情况发生。本文将着重介绍如何通过使用Redis与数据库相结合的方案来实现数据一致性。

数据不一致产生的原因:

首先,读取数据时都是先查询Redis,命中则直接返回,未命中则先查询数据库,再写入缓存并设定超时时间,因此不会有问题;

在修改数据时会出现以下问题:

1.先删除缓存再修改数据库

线程A先删除缓存,线程B读取缓存为空,然后读数据库并把数据加入缓存,线程A再修改数据库,此时缓存的是脏数据

2.先修改数据库再删除缓存

线程A先读取缓存为空然后查询数据库,线程B修改数据库后删除缓存,线程A把线程B修改前查询到的数据更新到缓存,此时缓存也是脏数据

解决方案:

延迟双删:

删除缓存、修改数据库后经过一定时间的延迟再删除缓存,让主数据库同步数据到从数据库。延迟双删不好控制延迟的时间,而且还会延迟的过程中可能会出现脏数据。

读写锁(强一致):

使用Redisson实现读写锁,在读的时候添加共享锁,可以保证读读不互斥,读写互斥。当我们更新数据的时候,添加排他锁,它是读写,读读都互斥,这样就能保证在写数据的同时是不会让其他线程读数据的,避免了脏数据。这里面需要注意的是读方法和写方法上需要使用同一把锁才行。

异步通知(延时一致):

1、使用RabbitMQ中间件,在数据发生更新后发一条消息到MQ,缓存服务监听MQ消息更新缓存。由于消息需要经过MQ,会有一定的延迟,所以是延时一致。

2、采用的阿里的canal组件实现数据同步:不需要更改业务代码,部署一个canal服务。canal服务把自己伪装成mysql的一个从节点,当mysql数据更新以后,canal会读取binlog数据,然后在通过canal的客户端获取到数据,更新缓存即可。

方案比较和选择:

  • 强一致性 vs 延时一致性:根据业务需求选择合适的数据一致性方案,权衡一致性级别和性能开销。
  • 性能和可靠性权衡:评估不同方案在性能和可靠性方面的特点,并根据需求做出选择。
  • 根据业务需求选择方案:考虑业务的实际需求,例如数据更新的频率、对数据实时性的要求以及系统的可扩展性。