连续调用多个外部系统的写接口-如何保证数据一致性(思路)

概述


某些场景下,我们将业务数据落地之前,是需要先调用外部系统的多个写接口,当这些写接口都操作成功了,我们才将业务数据落地到自己本地的数据库里面。比如说:

public void updateProductInfo(Product product) {
    //1、将商品价格更新到价格系统
    priceService.updatePrice(product);
    
    //2、将库存信息更新库存系统
    stockService.updateStock(product);

    //3、将商品更新到本地数据库
    productService.updateProduct(product);
}

就上面这个例子(例子是虚构的,只是为了说明问题而已),它的执行路径有几种:

1、调用价格系统、库存系统的操作以及保存数据到本地DB都正常;
2、调用价格系统接口的时候就抛异常了;
3、调用价格系统接口正常,但是调用库存系统的接口有异常;
4、调用价格系统和库存系统的接口都正常了,但是将商品数据更新到本地数据库出现异常。

如果是第一和第二这两种情况,无需考虑数据一致性问题,但是如果出现了第三和第四这两种情况,我们就得根据业务实际情况,考虑如何保证数据的一致性。

这里说的保证数据一致性,必须是由调用方来保证的,服务端是无法保证的。


重试和操作日志


以上面提到的第三种情况来说明一下。

调用价格系统接口正常,但是调用库存系统的接口有异常。

库存接口允许重试

如果库存系统接口是幂等的,那么调用方可以使用重试的机制,多调用几次,比如说3次。如果还是不成功,那之前价格系统接口的操作就得走反向操作,进行现场恢复。

####库存接口不允许重试
价格系统接口的操作得走反向操作,进行现场恢复


要实现反向操作,恢复现场,有一种办法是使用分布式事务,但是实现起来实在太复杂了,性能也不好。可以尝试使用操作日志来恢复现场。比如说,价格系统调用成功了,把这个操作状态以及相关的业务数据记录起来,当库存操作失败后,利用操作日志里的数据,将之前的价格操作恢复回来。这个恢复操作,价格系统可以单独提供出一个接口。

如果恢复现场的操作也失败了,这个时候只能人工介入解决了。没其他办法了。

  • 0
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
### 回答1: 要解决外部发号接口调用修改status值的锁问题,可以采取以下措施: 1. 使用锁机制:在程序中加入锁机制,确保同一时间只有一个请求可以修改status值,避免多个请求同时修改导致数据混乱。 2. 接口权限控制:对外部发号接口的访问进行权限控制,只有具备修改status值权限的请求才能进行修改。 3. 数据库事务控制:在修改status值的操作中开启数据库事务控制,确保操作原子性,如果其中一个操作失败,整个操作将回滚,避免数据错误。 4. 参数验证:在接口调用时对传入的参数进行验证,确保参数合法有效,防止参数错误导致的数据错误。 以上措施可以帮助解决外部发号接口调用修改status值的锁问题。 ### 回答2: 外部发号接口调用修改status值的锁问题,可以通过以下几种方法来解决: 1. 引入分布式锁:使用专门的分布式锁服务,例如ZooKeeper或Redis等,来保证同时只有一个线程可以修改status值。当有外部发号接口调用时,先获取锁并修改status值,然后释放锁,确保并发操作的线程安全性。 2. 使用乐观锁:在status字段上引入一个版本号,当有外部发号接口调用时,先读取当前status值和版本号,然后修改status值和增加版本号。在更新status值时,根据版本号判断是否允许更新,如果版本号一致则允许更新,否则表示已被其他调用修改,则需要重试或抛出冲突异常。 3. 使用悲观锁:在有外部发号接口调用时,使用数据库事务锁或数据库行锁等机制,在修改status值的过程中将该行数据锁定,阻止其他并发操作对status值的修改,待事务提交后释放锁。 4. 通过消息队列实现异步处理:当有外部发号接口调用时,将要修改status值的操作作为一个消息发送到消息队列中,通过消息队列的消费者来处理该消息并修改status值。由于消息队列中消息的顺序性,可以保证同时只有一个消费者在处理该消息,从而避免并发修改status值的问题。 在选择解决方案时,应根据具体场景和需求综合考虑,例如并发量、数据一致性要求和系统复杂度等因素。 ### 回答3: 外部发号接口调用修改status值的锁问题可以通过以下方式来解决: 1. 使用互斥锁:在外部发号接口调用的代码块中,使用互斥锁来保护对status值的修改操作。当一个线程获取到锁时,其他线程则无法同时进行修改的操作,从而避免了同一时间对status值的并发修改。 2. 使用原子操作:对于status值的修改操作,可以使用原子操作来确保其在多线程环境下的原子性。原子操作是指不会被中断的操作,可以一次性完成。通过使用原子操作,可以避免出现多线程并发修改导致的状态不一致问题。 3. 使用分布式锁:如果外部发号接口调用是在分布式系统中进行的,可以选择使用分布式锁来解决锁问题。分布式锁可以确保在多个节点中只有一个节点可以对status值进行修改操作,避免了多个节点同时修改的问题。 4. 使用事务:如果外部发号接口调用是在数据库事务中进行的,可以使用数据库事务来解决锁问题。通过在事务中对status值进行修改,并设置合适的隔离级别,可以避免在并发环境下出现状态不一致的问题。 无论采用哪种方式,都需要对代码进行合理设计和测试,以确保在多线程环境下对status值的修改操作能够正确地进行。同时,还需要考虑并发修改的概率和频率,以选择最合适的解决方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值