MQ 会自动定时轮询所有 prepared 消息回调你的接口,问你,这个消息是不是本地事务处理失败了,所有没发送确认的消息,是继续重试还是回滚?一般来说这里你就可以查下数据库看之前本地事务是否执行,如果回滚了,那么这里也回滚吧。这个就是避免可能本地事务执行成功了,而确认消息却发送失败了。
这个时候就需要自己实现反查接口。
如果这个方案里,要是系统 B 的事务失败了咋办?重试咯,自动不断重试直到成功,如果实在是不行,要么就是针对重要的资金类业务进行回滚,比如 B 系统本地回滚后,想办法通知系统 A 也回滚;或者是发送报警由人工来手工回滚和补偿。
最大努力通知最大努力通知,其实也算是一种最终一致性的方案。
主要是当A系统执行完本地事务后,发送消息给MQ,然后去让B系统执行事务操作,如果B系统执行完成了,就消费消息,若B系统执行失败了,则执行重试,重试多次直到成功。若达到一定次数后还没成功就只能人工干预了。
总结可靠消息那部分是因为我没有用过RocketMQ,所以并没有认真写,因为我目前在的是腾讯系的公司所以。。。
总结一下面试的时候如果被问到这个问题怎么办,其实就是根据实际的业务场景来看,像涉及到交易,订单等这种强一致性的场景,可以使用TCC,虽然说对也侵入性大,但是最终目的是很好的保证了。
还有就是对于时效性要求不是很强的,我觉得的最大努力通知也可以的。
最后说一下我们的目前使用的方案;
也算是最大努力通知的一种吧,当在一个web服务中,调用多个服务时,如何保证多个服务执行时数据一致性的。
当事务请求调用服务A时,如果服务A的操作执行失败了,那么直接事务执行失败。
如果执行服务A的事务成功了,但是执行服务B的事务失败了,那么我们会先将失败的请求落地(请求参数和被调用方信息入到消息表),然后将请求抛到消息队列中去进行重试,通过消息队列的ACK机制,保证我们重试消息最终可以被消费成功。
主要重试次数是3次,每次的重试的时间间隔不一样,重试三次之后如果消息还没有被ACK,那么就直接发送预警通知给开发人员,进行人工干预。
如果发送消费失败了,我们还有定时任务去定时刷我们的数据库里的消息表,来保证消息一定会被发送。
另外在真实涉及到支付,订单交易的场景时,我们主要也是使用类似TCC的方式来保证的。
说是类似是因为,我们只有CC。要么成功,要么不成功,就直接调用回撤接口进行回滚。