MST
星途 面试题库

面试题:Redis消息队列在MySQL广告投放系统中的数据一致性保障

在MySQL广告投放系统中使用Redis消息队列,如何确保消息处理过程中数据在Redis和MySQL之间的一致性?请描述可能用到的技术手段和实现思路。
47.1万 热度难度
数据库Redis

知识考点

AI 面试

面试题答案

一键面试
  1. 使用事务和持久化
    • Redis事务
      • 在Redis中,使用MULTI、EXEC命令来开启和执行事务。例如,当往Redis消息队列添加消息时,将添加操作和设置相关状态(如消息已入队标记)放在一个事务中。这样可以确保这些操作要么全部成功,要么全部失败,保证Redis内部数据的一致性。
      MULTI
      RPUSH ad_queue "new_ad_message"
      SET ad_queue_status "new_message_added"
      EXEC
      
    • Redis持久化
      • 配置Redis的持久化策略,如AOF(Append - Only - File)或RDB(Redis Database)。AOF会以日志的形式记录每一个写操作,RDB则是定期将Redis数据快照保存到磁盘。通过合理配置持久化策略,即使Redis重启,也能恢复到故障前的状态,保证消息队列中的数据不丢失。例如,对于AOF,可以设置appendfsync always,每次写操作都同步到AOF文件,但这样会影响性能;或者设置appendfsync everysec,每秒同步一次,在性能和数据安全性之间取得平衡。
  2. 使用两阶段提交(2PC)思想
    • 第一阶段(准备阶段)
      • 当有消息需要处理并写入MySQL时,先在Redis中标记该消息为“准备处理”状态。例如,使用一个Hash结构来记录消息的ID及其处理状态。
      HSET ad_message_status {message_id} "preparing"
      
      • 同时,在MySQL中开启一个事务,但不提交。执行相关的SQL操作,如插入广告投放记录到MySQL表中。
    • 第二阶段(提交阶段)
      • 如果MySQL中的操作都成功,在Redis中将消息标记为“已处理”状态。
      HSET ad_message_status {message_id} "processed"
      
      • 然后提交MySQL事务。如果在任何一个环节出现错误,在Redis中回滚消息状态为“未处理”,并回滚MySQL事务。
  3. 消息确认机制
    • 生产者端
      • 生产者向Redis消息队列发送消息后,等待消费者的确认消息。例如,生产者使用Redis的发布 - 订阅模式,消费者处理完消息后,向一个特定的频道发布确认消息。生产者监听这个频道,只有收到确认消息后,才认为消息成功处理。
    • 消费者端
      • 消费者从Redis消息队列取出消息并处理成功后,在MySQL中插入一条确认记录,记录消息ID及处理成功的时间等信息。同时,向Redis发布确认消息。如果处理失败,根据业务需求决定是否重新将消息放回队列,或者记录失败信息到另一个地方(如MySQL的错误记录表)。
  4. 数据校验和补偿机制
    • 定期校验
      • 定时任务定期检查Redis消息队列的状态和MySQL中的数据。例如,对比Redis中标记为“已处理”的消息ID和MySQL中实际存在的广告投放记录的ID。如果发现Redis中有“已处理”但MySQL中不存在对应记录,或者MySQL中有记录但Redis中没有标记为“已处理”的情况,进行补偿操作。
    • 补偿操作
      • 对于Redis中有“已处理”但MySQL中不存在对应记录的情况,重新执行MySQL插入操作;对于MySQL中有记录但Redis中没有标记为“已处理”的情况,在Redis中更新消息状态为“已处理”。可以通过编写脚本来实现这些补偿逻辑,定期运行该脚本以修复不一致的数据。