当调用外部接口发生异常、服务器宕机或杀死进程时如何保证数据一致性
调用外部接口发生异常时数据一致性解决方案
这里提供一个一劳永逸的解决方案
设计思路:
外部接口多采用交易接口+结果查询接口的方式,基于这种形式的接口提供以下解决方案。
1.根据流水号标识一笔交易请求,另外本地要提供rollback方法
2.模板类记录请求日志,日志状态在本地事务更新
3.定时任务扫描日志表异常或超时记录,然后调用外部查询接口进行补偿,对成功请求更改日志状态
4.如果外部接口返回失败,则调用rollback方法进行回滚
5.如果外部接口实现了密等性,可根据流水号(类全局事务ID)进行重试
该方案实现了对外部接口调用的密等性
日志表结构
根据具体业务增加字段
CREATE TABLE `trade_log` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`serial_num` varchar(32) DEFAULT '' COMMENT '流水号',
`message` varchar(1000) DEFAULT '' COMMENT '请求报文',
`log_status` varchar(10) DEFAULT 'INIT' COMMENT '日志状态:INIT-初始化,LOCAL_SUC-本地事务成功,SUC-事务成功,FAIL-事务失败',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '修改时间',
PRIMARY KEY (`id`),
UNIQUE KEY `uk_serial_num` (`serial_num`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
流程图
扩展延伸
分布式事务问题可基于BASE理论解决,现在较流行的TCC和基于可靠消息的最终一致性解决方案都是对BASE理论的实现
TCC实现有tcc-transaction(gitbub)、hmily(码云)、fescar
可靠消息最终一致性:新版本的RocketMq支持事务的回查,可保证消息不丢失