我最近遇到了这样的问题:
对于每个用户,我需要在服务器端执行以下操作:
First
(SQL) Insert user's record with a Unique constraint on ID
Then Parallel
(Http) Subscribe user to Service A, get subscription_id_A
(Http) Subscribe user to Service B, get subscription_id_B
Finally
(SQL) Update user's record with both subscription ids
理想情况下,我希望整个操作都是事务性的,例如,如果任何http请求或sql失败,就好像什么都没发生一样。补充说:如果请求A失败但B成功,我将被卡住:我是否取消了该事务并最终得到了一个未跟踪的订阅,或者我是否提交了它并最终导致用户错过了一个订阅
鉴于这可能无法实现,那么我能做的最好的事情是什么呢?
服务A和B确实提供了API来检查是否存在订阅以及修改,删除订阅,但我想避免使用Check Then Act样式。 SQL服务器具有最高的隔离级别
答案 0 :(得分:1)
这确实是一个标准问题。 (通常,开发人员不会意识到这个问题,只能在生产中找到。)没有标准的解决方案。一般来说,这是不可能解决的(参见http://en.wikipedia.org/wiki/Two_Generals%27_Problem - 两个系统永远不能100%确定是否应该提交或中止)。
也许您可以先执行所有SQL工作。插入用户但没有订阅ID。然后,您尝试逐个添加订阅,并在获得它们后在单独的事务中添加它们。
安装后台作业,定期检查很久以前创建但尚未订阅的用户。如果您发现任何差异,请修复它们并记录下这一事实。
此定期清理可确保临时故障(由于网络故障,超时,重新部署,错误等而发生 )是暂时性的。如果您愿意,它还可以确保检测到它们并向开发人员报告。
这将是一个最终一致的系统。我们的想法是首先以事务方式记录目标状态(用户和创建两个订阅的目标),然后让后台作业尝试将数据收敛到目标状态。