MST

星途 面试题库

面试题:高并发场景下Redis缓存失效与MySQL数据一致性保障策略

假设处于高并发读写的业务场景,大量请求同时访问Redis和MySQL,当Redis缓存失效时,如何设计一套健壮的机制来保障MySQL数据与Redis新缓存数据的一致性,需要考虑性能、数据准确性以及系统的稳定性等多方面因素。
25.7万 热度难度
数据库Redis

知识考点

AI 面试

面试题答案

一键面试
  1. 读写锁机制

    • 读操作
      • 在读取数据时,先尝试获取读锁。如果读锁获取成功,检查Redis缓存中是否存在数据。若存在,直接返回缓存数据;若不存在,从MySQL读取数据,将数据写入Redis缓存,并释放读锁,返回数据。
    • 写操作
      • 在写入数据时,先获取写锁。获取成功后,更新MySQL数据,然后删除Redis缓存(而不是直接更新Redis缓存,防止在更新MySQL过程中出现异常,导致MySQL和Redis数据不一致),最后释放写锁。这种方式通过锁机制保证了同一时间只有一个写操作,避免写 - 写冲突和写 - 读冲突,保证数据一致性,但读操作可能会因为等待锁而有一定延迟。
  2. 异步更新缓存

    • 写操作
      • 当数据更新请求到达时,先更新MySQL数据。更新成功后,将更新缓存的任务放入消息队列(如Kafka、RabbitMQ等)。这样主业务流程可以快速返回,提高了系统性能。
    • 缓存更新任务处理
      • 专门启动一个消费者服务监听消息队列。当监听到有更新缓存的任务时,从MySQL中读取最新数据(再次读取是为了确保数据准确性,防止在更新MySQL到处理消息队列期间数据又被其他请求更新),然后将数据写入Redis缓存。这种方式在保证数据一致性的同时,提高了系统的响应性能,但增加了系统的复杂度,需要处理消息队列的相关问题,如消息丢失、重复消费等。
  3. 双写一致性方案

    • 写操作
      • 同时更新MySQL和Redis数据。为了保证操作的原子性,可以使用事务机制(如果数据库支持对外部系统操作的事务),或者采用重试机制。
      • 例如,先更新MySQL,若成功,再更新Redis。如果更新Redis失败,记录失败日志,并启动重试逻辑。重试次数可以设置一定阈值,若多次重试仍失败,可以通过人工介入或告警通知运维人员处理。
    • 读操作
      • 读操作还是先从Redis读取数据,若不存在则从MySQL读取并更新Redis。这种方式实现相对简单,但在高并发下可能存在一定的一致性风险,因为更新MySQL和Redis不是真正的原子操作,不过通过重试机制可以尽量降低风险,保证数据的最终一致性。 同时,这种方案对性能有一定影响,因为每次写操作都需要操作两个存储系统。
  4. 版本控制

    • 数据结构设计
      • 在MySQL表中增加一个版本号字段。每次数据更新时,版本号自增。
    • 写操作
      • 更新MySQL数据的同时,更新版本号。然后将新数据和版本号一起写入Redis缓存。
    • 读操作
      • 从Redis读取数据和版本号。在读取MySQL数据时,比较MySQL中的版本号和Redis中的版本号。如果Redis中的版本号小于MySQL中的版本号,说明Redis数据不是最新的,从MySQL读取最新数据并更新Redis缓存及版本号。这种方式通过版本号的对比来保证数据一致性,性能上读操作增加了一次版本号对比,但相对开销较小,而且在高并发下能较好地保证数据准确性和系统稳定性。