MST

星途 面试题库

面试题:复杂业务场景下Redis与MySQL事务集成的故障恢复策略

设想一个复杂的电商业务场景,涉及库存管理(Redis实现)、订单创建与支付(MySQL实现)等多个环节,当系统在事务执行过程中发生故障(如网络中断、服务器崩溃等),请详细阐述如何设计一套完整的故障恢复策略,确保Redis事务与MySQL事务的最终一致性,并且尽量减少对业务的影响。
41.9万 热度难度
数据库Redis

知识考点

AI 面试

面试题答案

一键面试
  1. 记录日志
    • MySQL
      • MySQL本身有重做日志(redo log)和回滚日志(undo log)。重做日志用于崩溃恢复(crash - recovery),确保在发生故障后已提交的事务能重新应用,保证事务持久性。回滚日志用于撤销未提交事务对数据的修改,在故障恢复时,如果事务未提交,利用回滚日志将数据回滚到事务开始前的状态。
      • 自定义日志表,在订单创建和支付相关操作前,将操作信息(如订单号、操作类型、操作时间等)插入到日志表中。这样可以在故障恢复时,清晰地了解事务执行到哪一步。
    • Redis
      • 由于Redis单线程模型,本身没有像MySQL那样复杂的日志机制。但可以通过开启AOF(Append - Only - File)持久化方式,AOF日志记录了Redis服务器执行的所有写操作命令。在故障恢复时,Redis可以重放AOF日志来恢复数据到故障前的状态。同时,可以自定义记录事务相关日志,例如在执行库存管理相关的Redis事务前,将事务操作内容(如商品ID、库存变更数量等)记录到一个日志文件或者一个特殊的Redis列表中。
  2. 故障检测与识别
    • 应用层监控:通过心跳机制,应用程序定期向服务器发送心跳包,若一定时间内未收到响应,则判定可能发生故障。同时,应用程序可以记录事务执行的状态和步骤,当发生故障时,将这些信息传递给故障恢复模块。
    • 数据库层面监控:MySQL可以通过监控数据库的运行状态,如进程是否存活、是否能正常响应SQL语句等。Redis可以通过PING命令检测是否能正常连接,若不能连接则视为可能发生故障。
  3. 故障恢复流程
    • MySQL故障恢复
      • 重启MySQL服务后,MySQL会自动进行崩溃恢复。它会根据重做日志将已提交的事务重新应用,确保已提交事务对数据的修改生效。对于未提交的事务,MySQL会根据回滚日志将数据回滚到事务开始前的状态。
      • 检查自定义日志表,对于那些已经开始但未完成的订单创建与支付事务,根据日志中的操作信息决定下一步操作。例如,如果日志显示订单已创建但支付未完成,且支付操作是由于故障中断,那么可以尝试重新发起支付请求(在保证幂等性的前提下),或者根据业务规则进行取消订单等操作。
    • Redis故障恢复
      • 重启Redis服务后,若开启了AOF持久化,Redis会重放AOF日志恢复数据。如果是因为网络中断等原因导致Redis事务未完成,检查自定义的事务日志(如记录在Redis列表中的日志),对于未完成的库存管理事务,重新执行未完成的操作,确保库存数据的准确性。例如,如果事务是扣减库存操作,而故障发生在部分扣减库存后,根据日志可以补全扣减操作,保证库存数量正确。
  4. 一致性校验与补偿
    • 定期校验:系统恢复正常运行后,定期(如每天凌晨业务低峰期)对MySQL中的订单数据和Redis中的库存数据进行一致性校验。例如,通过订单中的商品信息和数量,与Redis中的库存数量进行比对。如果发现不一致,根据业务规则进行补偿操作。
    • 补偿操作:如果发现订单中商品数量大于Redis中的库存数量,可能是库存扣减操作未完全成功。此时可以根据情况选择通知管理员人工处理,或者尝试从其他仓库调配库存,同时在订单表中记录相关处理信息。如果订单中商品数量小于Redis中的库存数量,可能是订单创建时库存扣减过多,需要将多余的库存加回到Redis中,并更新相关记录。
  5. 保证业务幂等性
    • 在订单创建和支付接口设计上,要保证接口的幂等性。例如,在支付接口中,每次支付请求都携带一个唯一的支付ID。当发生故障后重新发起支付请求时,系统先检查该支付ID是否已经处理过,如果已经处理过则直接返回之前的支付结果,避免重复支付。
    • 在库存管理中,对于库存扣减操作也保证幂等性。例如,通过版本号机制,每次扣减库存前先获取当前库存版本号,扣减操作中携带版本号,若版本号一致则进行扣减并更新版本号,若不一致则说明库存已被其他操作修改,需要重新获取库存信息再进行操作,防止重复扣减或错误扣减。