【发布时间】:2015-07-02 18:56:46
【问题描述】:
我有以下(有缺陷的)分布式架构,它有竞争条件。我知道你们中的一些人可能对这个经典的“分布式状态传播问题”有解决方案——我很想听听他们的意见。如果你能容忍我,这是架构:
假设您有两个 golang 应用服务器,S1 和 S2。
还有两个 Cassandra 数据库节点,DB1 和 DB2。
S1 和 S2 分别连接到 DB1 和 DB2。
一个用户几乎同时从两个浏览器做两件事:
- 他打开客户端浏览器 C1,该浏览器将通过 websockets 连接到 S1 并请求从 DB1 或 DB2 获取状态。消息 M1 包含状态并从 S1 发送到 C1。
- 他打开客户端浏览器 C2,它将连接到 S2 以切换某些状态。 S2 将在 DB1 或 DB2 中更新该状态。然后 DB1 和 DB2 将相互同步。 S2 还需要告诉 C1 新状态,并使用 NSQ(或您喜欢的消息队列)将此状态更新消息发送给 S1,然后 S1 将带有状态更改的消息 M2 发送给 C1。
现在,在 (1) 和 (2) 之间存在毛茸茸的竞争条件。在 C1 上,什么先到达,M1 还是 M2? M1 可能包含或不包含 M2 中包含的状态更新,具体取决于 Cassandra 传播相对于 C1 请求的时间。
我意识到幂等消息或 CRDT 可以在某些用例中解决这个问题,但不是全部——尤其是对于非单调状态变化,如布尔切换状态。
我知道 OST(操作状态转移)也可以解决这个问题,但我不知道有什么好的现成解决方案。我之前已经建立了一个 OST 系统,它是一个主要的 PITA。
当然,可以拥有一种更一致的数据库,这使得这更易于处理,但我需要具有分区容错性的高可用性,这意味着要处理最终的一致性。
拥有数据库挂钩/回调可能会解决此问题,应用服务器可以在其中侦听特定状态的更改,并在状态传播到达该数据库节点时收到通知。我知道这些钩子存在于 Rethinkdb 等一些一致的数据库中,但(据我所知)它们不存在于 Cassandra 或任何其他高可用性 (HA)、分区容错 (PT) 数据库中。
我发现自己渴望应用程序级的状态抽象:跨平台;与 HA/PT 分布式持久存储集成;为我处理状态传播;并且可以在状态更改时轻松触发行为。我不知道这样的事情。
您知道哪些工具或架构可以满足这些限制:
- 没有竞争条件
- 高可用性、分区容错(最终一致)
- 处理非单调状态变化
【问题讨论】:
标签: state distributed-computing race-condition distributed-system eventual-consistency