redis和mysql的双写问题

什么是双写问题

Redis和MySQL的双写问题是指在同一个业务流程中,需要同时向Redis和MySQL两个数据库系统写入数据。由于这两种数据库系统的特性不同,可能会引发一些问题,尤其是在数据一致性和数据可靠性方面。

这主要有两个问题:

  1. 数据一致性问题:由于网络、程序等问题,可能会出现先写Redis成功,再写MySQL失败的情况,或者反过来,导致数据在两个系统中不一致。
  2. 双写一致性问题:即使两个写操作都成功,但由于Redis和MySQL的读写速度差异,可能会出现”脏读”的问题,即新的读操作读取到的是旧的数据。

解决策略

解决这两个问题的常见策略包括:

  1. 使用分布式事务来保证数据一致性。分布式事务可以保证在多个系统中的所有操作都成功或者都失败。但是,由于Redis并不原生支持分布式事务,实现起来可能比较复杂,且可能会影响系统性能。
  2. 采用最终一致性模型,这种模型可以接受短暂的数据不一致,但需要保证最终数据的一致性。例如,可以使用消息队列来实现:先更新一种数据库,然后将更新操作放入消息队列,由另一种数据库消费该队列来完成更新。
  3. 优先保证MySQL的数据写入,成功后再写入Redis。当读取数据时,优先从Redis中读取,如果Redis中没有,再从MySQL中读取,并将读取到的数据写入Redis,这种方式被称为缓存穿透。这种方式可以在一定程度上保证数据的一致性,但可能会增加系统的复杂性。

先写MySQL在写Redis的优缺点

优点:

  1. 数据一致性:优先保证MySQL的数据写入,成功后再写入Redis,这样即使在写Redis的过程中出现了错误,数据依然可以从MySQL中取得,这保证了数据的一致性。
  2. 高可用性:读取数据时,优先从Redis中读取,如果Redis中没有,再从MySQL中读取,并将读取到的数据写入Redis。这样做既可以提高数据读取的速度(因为Redis是基于内存的,读写速度快),又可以防止MySQL的查询压力过大。
  3. 易于实施:这种策略在技术实现上相对简单,不需要考虑分布式事务或者引入额外的组件如消息队列等。

弊端:

  1. 数据延迟:由于数据需要先写入MySQL,再写入Redis,所以如果有并发的读请求,可能会读到旧的数据,也就是出现“脏读”的情况。
  2. 增加系统复杂性:这种方式需要业务代码去做缓存的读写,增加了代码的复杂性。
  3. Redis数据丢失问题:如果Redis发生故障,数据丢失,会导致大量的请求冲击MySQL,进一步可能会引发MySQL的性能问题。这种情况下,需要有适当的Redis持久化策略,或者备份策略来应对。

适用场景

  1. 高读取频率的数据:对于读取频率很高的数据,这种策略非常有用。数据主要存储在MySQL中,但由于读取主要从Redis中进行,可以显著提高读取速度。
  2. 需要快速更新的数据:对于需要快速更新的数据,首先更新MySQL,然后更新Redis,这样可以保证最终的数据一致性。(或者可以先让Redis数据失效,在更新数据库,Redis等下一次查询的时候进行更新)
  3. Redis数据失效或重启:当Redis中的数据失效或者Redis需要重启时,可以从MySQL中读取数据并重新填充Redis,这样即使Redis中的数据丢失,也不会影响到应用程序的正常运行。

分布式事务

有几种常见的分布式事务解决方案,包括两阶段提交(2PC)、三阶段提交(3PC)、TCC(Try-Confirm-Cancel)等。这里我会详细介绍2PC和TCC两种方案。

  1. 两阶段提交(2PC)

    • 准备阶段:事务协调者向所有的事务参与者发送事务内容,询问是否可以执行事务,然后等待所有参与者的回复。
    • 提交阶段:如果所有的事务参与者都同意事务请求,事务协调者向所有的参与者发送“提交”请求,并进入“完成”状态。各参与者在执行事务提交操作后,释放在事务执行中占用的资源。

    这种方式的主要问题在于同步阻塞和单点问题。如果协调者宕机,参与者会一直阻塞等待,直到协调者恢复。如果参与者宕机,协调者也需要一直等待其恢复。此外,事务的提交依赖于所有参与者的反馈,只要有一个参与者反馈失败,那么整个事务就会失败,这显然在大规模分布式系统中是低效的。

  2. TCC(Try-Confirm-Cancel)

    • Try阶段:检查预计执行的业务是否可以成功,执行所有业务检查,预留必须的业务资源。
    • Confirm阶段:真正的执行业务操作,并且不会失败(除非有程序上的错误),因为前一阶段已经做了资源的预留。
    • Cancel阶段:在业务执行错误,或者长时间无响应需要回滚的时候,执行的业务取消,取消预留的业务资源。

    TCC模式相比于2PC,更适合长事务处理,能更好地降低阻塞情况。但TCC需要为每个业务逻辑编写对应的确认和取消操作,增加了开发的复杂性。


redis和mysql的双写问题
http://coder-xieshijie.cn/2023/08/06/数据库/Redis/redis和mysql的双写问题/
作者
谢世杰
发布于
2023年8月6日
许可协议