[Robinhood] 关于Distributed Transaction

上课讲的用Saga pattern来作为distributed transaction的方案,保证reserve balance, create order, submit order to external venue, update order, update balance是一致的,概念上理解了,但是实际上这个watchdog是怎么work的不太清楚

watchdog接收account service, order service etc的message之后,怎么决定要不要修复呢?
比如

  1. account service reserve balance之后call order service超时,那watchdog要不要介入?
  2. order service call external venue超时,连ID都没返回,那watchdog怎么办?

另外order service和distributed service都talk to internal DB,可不可以直接做一个DB上的transaction,这样就省去了一步distributed transaction

谢谢老师!

问:account service reserve balance之后call order service超时,那watchdog要不要介入?
答:需要介入,确认 order service 没有对 order 进行处理以后,可以重试。如果多次重试失败,可以 rollback - release account balance

问:order service call external venue超时,连ID都没返回,那watchdog怎么办?
答:等到超时之后,用 internal transaction id 给 external venue 发一个 get request, 确认一下状态。

问:order service和distributed service都talk to internal DB,可不可以直接做一个DB上的transaction,这样就省去了一步distributed transaction
答:Group 在一起的前提是同一个 microservice 向 DB 发出多个 write request。在这里我们有两个 microservice,就不能直接使用 DB 自带的 transaction 了。当然,如果我们合并 order 和 account service,就可以考虑使用 DB 自带的 transaction。

谢谢老师!后面两个问题明白了,对于第一个问题:

  1. watchdog什么时候介入呢?比如超时设了2秒,那watchdog是发现过了2秒还没有order service的log,就重试吗?那watchdog还需要对于每个request的状态进行存储?

  2. 如果重试的话具体是怎么完成的,是watchdog call order service, 还是发个order service subscribe某个topic然后watchdog发消息?

  1. 重试是根据每个 request 来决定的,watchdog 会存储每个 request 状态。
  2. 通过 Kafka 会比较好一点,watchdog 发送一个恢复状态的 event,然后 order service consume 这个 event。

想问下 关于“account service reserve balance之后call order service超时,那watchdog要不要介入?”
下面这篇老师说不要重试, 因为不能保证exact once, 这篇说重试后再rollback

best practice应该是怎么样呢

我对这个问题的理解也是越来越深了, 之前讲得不太好的地方请包涵。
是要重试的,这个重试需要有 idempotent key,这样不会导致订单处理多次。这种情况下 account service 自己重试就可以了,不用 watchdog。如果多次失败,再由 watchdog/transaction manager 回滚 reserve cash 的操作。

所以account db也要存 idempotent key 吗 还是account service也需要一个transaction table

account service replay 一个 request 的时候需要传 idempotent key。这个不在 account table 里存,可以额外开一个 table 存所有用户传过来的 request 和这个 request 的目前状态。每次来的时候我们马上记录下来,配置一个 idempotent key。