【问题标题】:Cross Service Transactions or Atomicity跨服务事务或原子性
【发布时间】:2019-08-05 14:55:54
【问题描述】:

我有一个实时程序,它使网络调用服务 A 以执行有状态操作,并通过网络调用服务 B 以记录该操作的历史记录。转折是:

  1. 如果 B 失败,我们必须恢复操作 A(出于“原因”,我们需要完整的历史记录,否则操作根本不会发生)。换句话说,除非我们已经明确且成功地调用了服务来执行操作,否则我们无法编写审计跟踪(即,我们不能更改先调用审计跟踪,然后调用服务的顺序)。
  2. 在 B 中存在我们无法拥有的无效历史排序(这是 A 的有状态方面)

我有一些想法,没有一个是理想的:

  • 在采取行动之前获取A的状态(这是一个可用的方法),如果对B的调用失败,我们可以再次以原始状态再次调用第一个服务。方法的问题是对 A 的“恢复”调用也可能失败。
  • 在较高级别上,这似乎可以通过服务级别的“事务”来解决(其中两个服务调用都成功或都失败)。主要算法似乎是2-phase commit,但它似乎不是我们可以使用的,因为我们不拥有我们正在调用的服务,因此无法保证稳定的存储,我们无法为其添加功能“同意”与“事务协调员”
  • 在我们这边实施我们自己的最大努力模拟交易。在我看来,这是一种相当复杂的方法,很难或不可能做到正确
  • 有能力进入“最终一致的状态”。但是,根据 2,某些排序是不可能的,因此我们必须等待所有排队的操作完成才能继续。这将使我们的服务可能不再是实时的

有没有什么解决方案可以让日志的完整镜像100%正确满足要求?

【问题讨论】:

    标签: transactions atomic distributed-computing soa distributed


    【解决方案1】:

    您没有提到所有服务都在使用的协议进行通信,为了回答这个问题,我假设是 HTTP。

    就像你说的那样,你可能的解决方案听起来都不适合你。

    1. 服务在状态检查之前或之后更改状态太容易了,就像您说的那样,之后的任何补救措施也很容易失败。

    2. 我认为在您概述的场景中,两阶段提交是不可能的。即使您确实拥有所有服务,仅使用 HTTP 也很难做到这一点。

    3. 我同意

    4. 在所有选项中,这个有腿。这完全取决于您对“实时”的要求。每当有人这么说时,我都会问“你是什么意思?”没有什么是“实时”的,一切都需要一些时间来处理。总有一段时间从某人或某事要求做某事到它真正完成!毫秒秒和分钟之间的差异只是一个问题或要求,以及您必须投入多少钱。

    所以你说通过 HTTP 调用你的服务(让我们称之为 X)再次通过 HTTP 调用两个服务 A 和 B。如果您同时对 X 进行多次调用,则无法(或至少很难)确保对 A 的调用顺序与对 B 的调用顺序相同。但这又取决于您的要求和什么系统在做什么以及如何,也许每天只有一个呼叫到您的系统?

    我个人建议使用队列,并转向事件驱动架构。即使使用最终一致的系统,您也可以让它热运行并获得您想要的“实时”,但这只会花费您更多!

    我希望这对你有用。我很想听听您对我的建议的看法。

    【讨论】:

    • 我认为几分钟是可以接受的等待时间,预计流量不会太高。虽然我认为要开发一种具有持久本地队列的解决方案需要付出很大的努力。
    • 在这方面有很多技术可以帮助您,您不会为此开发新的解决方案。看看当今云提供商提供的所有技术。我们在 AWS 中大量使用 sqs,如果您在本地可以使用 kafka、zeroMQ 或 rabbitMQ 这么多选项。开发事件驱动系统比您想象的要容易。
    猜你喜欢
    • 1970-01-01
    • 2017-05-30
    • 2015-07-13
    • 2015-07-24
    • 2011-08-06
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多