MST

星途 面试题库

面试题:缓存设计之高级难度:缓存与消息队列的一致性保障方案

在一个涉及订单处理的后端系统中,数据同时存在于数据库、缓存和通过消息队列进行异步处理。当订单状态发生变化时,如何确保缓存、数据库和消息队列处理结果之间的数据一致性?请详细说明设计思路、可能遇到的问题及相应的解决方案。
32.9万 热度难度
后端开发缓存设计

知识考点

AI 面试

面试题答案

一键面试

设计思路

  1. 数据库优先:订单状态变化首先持久化到数据库,确保数据的可靠性和持久性。使用数据库事务保证状态变化操作的原子性,避免部分更新导致数据不一致。
  2. 缓存更新:数据库更新成功后,同步更新缓存。可以采用两种方式:
    • 直写式:在更新数据库后立即更新缓存,保证缓存与数据库数据实时一致。
    • 失效式:更新数据库后使缓存中对应订单状态的缓存项失效,下次读取时重新从数据库加载并更新缓存。
  3. 消息队列处理:数据库更新成功后,发送包含订单状态变化信息的消息到消息队列。消息队列消费者负责根据消息内容进行异步业务处理,处理完成后再次检查数据库中订单状态,确保处理结果与数据库状态一致。

可能遇到的问题

  1. 缓存与数据库更新顺序问题:如果先更新缓存,后更新数据库,在数据库更新失败时,缓存与数据库数据不一致。如果先更新数据库,后更新缓存,在高并发场景下,可能出现缓存更新延迟,导致短暂的数据不一致。
  2. 消息队列处理失败:消息可能因为网络问题、消费者故障等原因处理失败,导致异步业务未完成,数据不一致。
  3. 并发访问:高并发场景下,多个请求同时更新订单状态,可能导致数据库、缓存和消息队列处理冲突。

解决方案

  1. 缓存与数据库更新顺序问题
    • 先更新数据库后更新缓存:采用重试机制,若缓存更新失败,进行多次重试。若重试多次仍失败,可记录日志并通过监控系统告警,人工介入处理。
    • 采用异步更新缓存:使用异步任务队列来更新缓存,减少主业务流程的响应时间。同时对异步任务进行监控,确保缓存更新成功。
  2. 消息队列处理失败
    • 重试机制:消息队列消费者设置重试策略,当处理失败时,按照一定的时间间隔进行重试。
    • 死信队列:对于多次重试仍失败的消息,发送到死信队列,后续人工分析处理死信队列中的消息。
    • 幂等性设计:确保消息队列消费者处理逻辑是幂等的,即多次处理同一消息得到的结果相同,避免重复处理导致数据不一致。
  3. 并发访问
    • 数据库锁:在数据库层面使用行锁或表锁,确保同一时间只有一个事务能更新订单状态。
    • 分布式锁:在高并发分布式系统中,使用分布式锁(如Redis锁、Zookeeper锁),保证同一时间只有一个服务实例能处理订单状态更新操作。