面试题答案
一键面试- 使用事务和持久化
- 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
,每秒同步一次,在性能和数据安全性之间取得平衡。
- 配置Redis的持久化策略,如AOF(Append - Only - File)或RDB(Redis Database)。AOF会以日志的形式记录每一个写操作,RDB则是定期将Redis数据快照保存到磁盘。通过合理配置持久化策略,即使Redis重启,也能恢复到故障前的状态,保证消息队列中的数据不丢失。例如,对于AOF,可以设置
- Redis事务:
- 使用两阶段提交(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事务。
- 第一阶段(准备阶段):
- 消息确认机制
- 生产者端:
- 生产者向Redis消息队列发送消息后,等待消费者的确认消息。例如,生产者使用Redis的发布 - 订阅模式,消费者处理完消息后,向一个特定的频道发布确认消息。生产者监听这个频道,只有收到确认消息后,才认为消息成功处理。
- 消费者端:
- 消费者从Redis消息队列取出消息并处理成功后,在MySQL中插入一条确认记录,记录消息ID及处理成功的时间等信息。同时,向Redis发布确认消息。如果处理失败,根据业务需求决定是否重新将消息放回队列,或者记录失败信息到另一个地方(如MySQL的错误记录表)。
- 生产者端:
- 数据校验和补偿机制
- 定期校验:
- 定时任务定期检查Redis消息队列的状态和MySQL中的数据。例如,对比Redis中标记为“已处理”的消息ID和MySQL中实际存在的广告投放记录的ID。如果发现Redis中有“已处理”但MySQL中不存在对应记录,或者MySQL中有记录但Redis中没有标记为“已处理”的情况,进行补偿操作。
- 补偿操作:
- 对于Redis中有“已处理”但MySQL中不存在对应记录的情况,重新执行MySQL插入操作;对于MySQL中有记录但Redis中没有标记为“已处理”的情况,在Redis中更新消息状态为“已处理”。可以通过编写脚本来实现这些补偿逻辑,定期运行该脚本以修复不一致的数据。
- 定期校验: