代码逻辑不知道怎么设计
最近在开发中碰到一个问题,不知道要怎么设计逻辑比较好。希望有大佬可以帮忙提个建议。
就是在一个接口里面,我需要 请求多个第三方接口,同时根据第三方接口更新数据库。
(1)如果把第三方接口放到数据库事务里面,会导致事务执行时间太长,性能会有问题。
(2)如果把第三方接口请求放到事务外面,又没法跟数据库事务保持一致。并且如果第三方接口执行了,但是数据库事务挂了,也是麻烦。
伪代码如下:
$api = new zfb();
$db = new db();
$db->begin();
try {
$res1 = $api->query(xxx);
$db->update($res1);
$res2 = $api->query2(xxx);
$db->update($res2);
$db->commit();
} catch (\Exception) {
$db->rollback();
}
:joy:请求完再一起放到一个事务里更新,或者单个请求完执行单个事务
第三方接口只是读取吗,请求了有什么影响
请求放到事务外面,每个请求可以赋给一个变量,如果都成功就在统一事务内更新
用第二种方式。将数据获取和入库分开。
把调用接口操作封装成一个方法,判断所有接口成功后返回最终所有接口数据,任何一个接口请求超时或失败,retry重新调用全部接口或者单个接口(更好)。可以使用辅助函数retry方法辅助函数《Laravel 8 中文文档》 或者使用队列处理可以,队列有失败重试机制。
数据库事务不会挂,除非mysql挂了。会出现死锁
DB::transaction 方法第二个参数可以处理死锁重试机制 快速入门《Laravel 8 中文文档》
如果第三方接口只是读查询,那就放到事务前全部请求; 如果第三方接口有写或依赖你的事务逻辑,简单的就是分步骤,根据你的业务情况,会有不同的复杂度,可以给主数据加个状态,支持继续下一步的操作,等等
看了你的贴子,你担心的问题无非两点。
反正我的思路还是异步分发,三个请求接口可耗不起,事务先提交,队列执行三次请求。
有异常记录日志,做好异常处理就行了,没必要过于担心这些。
第一点 弄清楚自己的需求
如果都是自己系统的很好处理
如果涉及第三方,第三方的是查询,还是操作,是否 可以进行挽回
第三方会不会执行失败
失败了怎么处理
还有就是 自己的 这个是否需要做同步处理 (是否可以用异步来出来, 异步不用担心响应速度)
拆分业务
解决方案:单接口事务就行了,没必要多个第三方接口打包事务。中间有失败的,也就是多个中间状态而已,后续根据状态再继续进行。抽象起来,就是个业务审批流,只不过没有人工去一步步操作而已。
上面大家已经说的比较详细了,你所关心的不同步问题,要根据具体业务来处理。
你请求的第三方接口是否有回滚操作,如果类似支付这种,无法回滚。那本地数据库更新失败,做好相关异常处理逻辑。 例如标记订单为异常订单,定时重试或者人工处理,主要是要保证所有数据都可溯,正常业务事务也不应该经常崩。
你这里可能没搞清楚,事务回滚跟你请求第三方接口没关系,事务失败了,只要你请求了第三方,还是请求了,并不会时光倒流, 这里可以异步或者同步,保证每一步都成功即可,不成功的做好错误处理机制即可
三方接口也该有回滚操作的。所以只对数据库做事务,事务失败使用三方接口回滚数据
可以参考下这个:
事务遇到第三方API请求如何处理 www.jianshu.com/p/afbf957501ce
如何优雅地重试 www.infoq.cn/article/5fboevkal0gvg...