【问题标题】:Service Fabric: Consistency when updating state between stateful servicesService Fabric:在有状态服务之间更新状态时的一致性
【发布时间】:2016-08-10 11:16:48
【问题描述】:

假设有状态服务中有这样的代码:

public async Task<bool> UpdateTheThing()
{
    using (var tx = StateManager.CreateTransaction())
    {
        await UpdateLocalState(tx);
        // point a
        bool isOK = await otherServiceProxy.UpdateServiceState();
        // point b
        if(isOK)
        {   
            await tx.CommitAsync();
        }
        return isOK;
    }
}

如果在我们安全之前的任何地方发生了不好的事情 - 交易将处理 确保数据一致。如果在 a 点和 b 点之间发生了什么事,我们可以 或者可能没有更新其他服务的状态。

如果发生的坏事是抛出异常,我们可以 恢复其他服务的状态,但如果我们的节点在那个时候被关闭,我们会 永远不要恢复状态。

我知道解决此类问题的一种方法是执行以下操作:

  1. 让 UpdateTheThing 除了将命令添加到队列之外什么都不做
  2. 实现一些逻辑来处理队列
  3. 发明某种方法将结果 (isOk) 返回给调用者
  4. 使 UpdateServiceState 幂等
  5. 如果出现问题,让队列继续重试命令
  6. 如果问题不断发生,请发明某种方法从队列中删除命令,并以某种方式通知某人存在问题。

这是相当多的基础设施。我正在寻找更简单方法的建议。

我注意到似乎没有一个 Service Fabric 示例可以处理此问题。

【问题讨论】:

    标签: architecture microservices azure-service-fabric


    【解决方案1】:

    我认为您上面描述的六步方法是正确的。 Service Fabric 目前不支持跨服务事务:

    UserVoice request to consider that feature

    我推测要么永远不会支持,要么可能以某种有限的方式支持。分布式系统中的事务一致性是一个已知的难题。这就是为什么最终一致性是现代云架构中当前首选模式的原因:

    eventual consistency description

    关于这个问题的更多背景知识:

    CAP theorem

    links to related research

    至于您的解决方案,我想说您的方法虽然不是很简单,但却是正确的。正如所写,UpdateTheThing() 有两种状态的隐含概念……“没有更新”和“一切都更新”。您需要引入调用者明确知道的其他一些状态,并相应地进行处理:

    • 没有更新
    • 本地状态已更新
    • 本地状态更新+远程状态更新请求发送
    • 本地状态已更新 + 调用者异步接收远程更新成功/失败的确认

    您可能还希望在超过特定超时期限等未收到远程更新确认后出现错误情况。您可能还希望重试行为等的正式状态。

    根据您的具体情况,显然还有很多复杂性。关键是您可能不希望 UpdateTheThing() 试图向调用者隐藏它的复杂性……调用者需要了解可能的状态并适当地处理/响应它们。

    正如您所说,它很复杂,但这就是分布式工作的本质(在云中或其他地方)。

    祝你好运!

    【讨论】:

      猜你喜欢
      • 2016-08-03
      • 2017-06-22
      • 1970-01-01
      • 2021-08-11
      • 1970-01-01
      • 2016-11-16
      • 2017-11-11
      • 2017-01-31
      • 2018-09-04
      相关资源
      最近更新 更多