在分布式事务系统中使用事务历史而不是余额
Using transaction history instead of balance in distributed transactional systems
前言
CAP 定理表明我们不可能拥有严格一致且可用的分布式系统。对于交易系统(例如某些支付系统),一致性通常优于可用性,因为我们不能容忍货币被“创造”或“销毁”的情况。
例子
A和B都想转$10给C,C的初始余额是$15。如果 A 和 B 同时读取 C 的当前余额并添加 $10 那么 C 将是 $25,但它应该是 $35 (15+10+10)
问题
使用交易历史记录和计算当前余额而不是存储余额是一个好习惯吗?这种方法的优缺点是什么?
我 reading\watching 有几个关于一致性和分布式系统的来源,但我还没有找到任何相关信息。
想法
优点:
- “创造”/“毁灭”金钱是不可能的。
- 无需与其他节点同步即可提交事务。
缺点:
- 可以透支。
- 可能需要更多计算才能显示余额。虽然可以通过缓存过去某个时间点的余额来缓解。
所以在我看来,这样的系统将是一致性和可用性之间的某种中间点...
您所描述的更正式地称为 operational CRDT。
是的,它可以以执行变异操作的方式工作。通常,这种方法有几个缺点。
第一个是操作不是幂等的(因为您在示例中将 difference/delta 应用于余额,而不是设置余额)。
其次,随着系统正常运行时间的增加,变化的增量将会累积。如果新参与者在任何时候想要了解您所指的余额,他们需要阅读所有历史记录并重新计算当前余额。如果您要处理大量更改,这可能是个问题。
为了避免这种情况,通常会进行某种形式的快照。但是,由于第三点,这可能很难构建。
第三,您的系统在任何时候都不能保证您的参与者对余额有一个统一的看法。
现在,根据你想做什么,我可以想出一些解决方案来解决这些问题。
例如,您可以为每个更新提供一个标识符 (UUID)。这会给你一定程度的信心,你的更新可以被幂等地应用。然后标识符也可以用作快照的方式(例如,所有余额直到 id X 为 1000)。然后,您网络中的新参与者只需阅读直到最后一个快照的操作历史记录。
创建快照会是一个有点问题的过程,但是,由于您的系统:所有参与者都必须同意直到 X 的余额是某个值。此时,您可能会发现一些参与者错过了历史片段,而不仅仅是最新的更新,因此他们必须重新同步。
前言
CAP 定理表明我们不可能拥有严格一致且可用的分布式系统。对于交易系统(例如某些支付系统),一致性通常优于可用性,因为我们不能容忍货币被“创造”或“销毁”的情况。
例子
A和B都想转$10给C,C的初始余额是$15。如果 A 和 B 同时读取 C 的当前余额并添加 $10 那么 C 将是 $25,但它应该是 $35 (15+10+10)
问题
使用交易历史记录和计算当前余额而不是存储余额是一个好习惯吗?这种方法的优缺点是什么?
我 reading\watching 有几个关于一致性和分布式系统的来源,但我还没有找到任何相关信息。
想法
优点:
- “创造”/“毁灭”金钱是不可能的。
- 无需与其他节点同步即可提交事务。
缺点:
- 可以透支。
- 可能需要更多计算才能显示余额。虽然可以通过缓存过去某个时间点的余额来缓解。
所以在我看来,这样的系统将是一致性和可用性之间的某种中间点...
您所描述的更正式地称为 operational CRDT。
是的,它可以以执行变异操作的方式工作。通常,这种方法有几个缺点。
第一个是操作不是幂等的(因为您在示例中将 difference/delta 应用于余额,而不是设置余额)。
其次,随着系统正常运行时间的增加,变化的增量将会累积。如果新参与者在任何时候想要了解您所指的余额,他们需要阅读所有历史记录并重新计算当前余额。如果您要处理大量更改,这可能是个问题。
为了避免这种情况,通常会进行某种形式的快照。但是,由于第三点,这可能很难构建。
第三,您的系统在任何时候都不能保证您的参与者对余额有一个统一的看法。
现在,根据你想做什么,我可以想出一些解决方案来解决这些问题。
例如,您可以为每个更新提供一个标识符 (UUID)。这会给你一定程度的信心,你的更新可以被幂等地应用。然后标识符也可以用作快照的方式(例如,所有余额直到 id X 为 1000)。然后,您网络中的新参与者只需阅读直到最后一个快照的操作历史记录。
创建快照会是一个有点问题的过程,但是,由于您的系统:所有参与者都必须同意直到 X 的余额是某个值。此时,您可能会发现一些参与者错过了历史片段,而不仅仅是最新的更新,因此他们必须重新同步。