MST

星途 面试题库

面试题:Redis和MySQL双写一致性问题及解决方案

在Redis与MySQL结合实现高效数据读取流程中,双写一致性是个常见难题。当数据发生变更时,需要同时更新Redis缓存和MySQL数据库。请详细分析可能出现不一致的场景,并给出相应的解决方案及优缺点。
17.7万 热度难度
数据库Redis

知识考点

AI 面试

面试题答案

一键面试

可能出现不一致的场景

  1. 先更新数据库,后更新缓存
    • 场景描述:应用程序先成功更新MySQL数据库,但在更新Redis缓存时发生异常失败。此时,后续读请求先从Redis缓存读取数据,就会读到旧数据,导致数据不一致。
    • 示例:商品价格在数据库中已更新为新价格,但Redis缓存中价格还是旧价格,用户查询到的就是旧价格。
  2. 先更新缓存,后更新数据库
    • 场景描述:应用程序先成功更新Redis缓存,但在更新MySQL数据库时发生异常失败。此时,其他进程可能读取到Redis中的新数据,但由于数据库未更新,在缓存失效后,后续读请求从数据库读取的是旧数据,导致不一致。
    • 示例:文章内容在Redis缓存中已更新,但数据库未更新成功,当缓存过期后,用户获取到的文章内容还是旧的。
  3. 高并发下的读写操作
    • 场景描述:在高并发场景下,一个写操作先更新了数据库,还未来得及更新缓存,此时多个读操作并发执行,先从缓存中读取到旧数据,然后写操作更新了缓存。后续读操作又会读到新数据,造成同一时间内数据读取不一致的“闪烁”现象。
    • 示例:电商商品库存,写操作更新库存到数据库后,还没更新缓存,多个读请求读取到旧库存,然后写操作更新缓存,后续读请求又读到新库存。

解决方案及优缺点

  1. 先更新数据库,后删除缓存
    • 解决方案:应用程序在更新MySQL数据库成功后,立即删除对应的Redis缓存数据。这样,下次读请求就会从数据库读取最新数据,并重新写入缓存。
    • 优点:实现相对简单,在大多数场景下能有效保证数据一致性。
    • 缺点:在高并发场景下,可能会出现短暂的不一致。例如,写操作更新数据库后,还没删除缓存,此时读操作读取到旧缓存数据,然后写操作删除缓存,后续读操作才从数据库读取新数据。
  2. 先删除缓存,后更新数据库
    • 解决方案:应用程序先删除Redis缓存数据,然后更新MySQL数据库。
    • 优点:同样相对简单,能在一定程度上保证数据一致性,减少了缓存中的旧数据被读取的概率。
    • 缺点:在高并发场景下,如果删除缓存后,还没更新数据库,此时读请求发现缓存不存在,会从数据库读取旧数据并写入缓存,然后写操作才更新数据库,就会导致缓存中的数据和数据库不一致。可以通过设置缓存过期时间来缓解,但不能完全避免。
  3. 使用队列
    • 解决方案:将数据更新操作放入队列中,按顺序依次处理。写操作先将更新数据库和更新缓存的任务放入队列,队列依次取出任务执行,保证更新操作的顺序性。
    • 优点:能有效解决高并发下读写操作导致的数据不一致问题,保证数据严格按顺序更新。
    • 缺点:增加了系统复杂度,需要引入消息队列中间件,可能会带来额外的性能开销和运维成本。
  4. 读写锁
    • 解决方案:在数据读写操作上加锁。写操作时,获取写锁,禁止其他读写操作,更新数据库和缓存成功后释放锁。读操作时,获取读锁,允许其他读操作并发执行,但禁止写操作,直到读锁释放。
    • 优点:能严格保证数据一致性,在读写频繁的场景下能有效控制并发。
    • 缺点:性能较低,加锁和解锁操作会带来额外开销,且可能导致死锁问题,需要复杂的锁管理机制。