我最近遇到这样的问题:
对于每个用户,我需要在服务器端执行以下操作:
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 Server 具有最高的隔离级别
最佳答案
这确实是一道标准题。 (通常,开发人员并没有意识到这个问题,只是在生产中才发现。)没有标准的解决方案。一般不可能解决(参见 http://en.wikipedia.org/wiki/Two_Generals%27_Problem - 两个系统永远无法 100% 确定它们应该提交还是中止)。
也许您可以先执行所有的 SQL 工作。插入用户但没有订阅 ID。然后,您尝试一个接一个地添加订阅,并在获得它们后将它们的 ID 添加到单独的事务中。
安装一个后台作业,定期检查很久以前创建但尚未订阅的用户。如果您发现任何差异,请修复它们并记录这一事实。
这种定期清理确保临时故障(将由于网络故障、超时、重新部署、错误等而发生)是临时的。如果您愿意,它还可以确保它们被检测到并报告给开发人员。
这将是一个最终一致的系统。这个想法是首先以事务方式记录目标状态(用户和创建两个订阅的目标),然后让后台作业尝试将数据汇聚到目标状态。
关于sql - 事务式 HTTP 请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28848628/