用 erlang 描述 tcc

Transaction 视为一个 Actor.

    start_transaction(Order) ->
        p1 = spawn(start_order(self, Order.subOrder1))   # 酒店
        p2 = spawn(start_order(self, Order.subOrder2))   # 航空公司
        p3 = spawn(start_order(self, Order.subOrder3))   # 汽车公司
        wait_try_success(Order, [p1, p2, p3])

    wait_try_success(Order, Actors) ->
        receive
            try_success ->
                if all_tried 
                    Actors.forEach(actor => actor ! confirm)
                    wait_confirm_success(Order, Actors)
            try_failed ->
                Actors.forEach(actor => actor ! cancel)
            timeout ->
                Actors.forEach(actor => actor ! cancel)
    
    wait_confirm_success(Order, Actors) ->
        receive
            confirm_success ->
                if all_confirmed 
                    done
            confirm_failed ->
                Actors.forEach(actor => actor ! cancel)
            timeout ->
                Actors.forEach(actor => actor ! cancel)                    

每个任务视为一个 actor,

    start_order(Transaction, Order) ->
        try()
        Transaction ! try_success
        wait_confirm(Transaction, Order)
    
    wait_confirm() ->
        receive 
            confirm ->
                    confirm()
                    Transaction ! confirm_success
            timeout ->
                    cancel()
                    Transaction ! failed            
            cancel ->
                    cancel()

发起人启动 Transaction, 该 Transaction 启动 order actor, 并进入 try.

order actor 收到订单时, 执行 try, 等待 confirm.

Transaction 收集满所有相关 actor 的 try_success 后, 通知 confirm.
收集齐所有 confirm_success 后, 事务完成.

  • 如收到 confirm_failed 后 try_failed, 则群发 cancel.
  • 如超时, 亦群发 cancel.

order actor 在 wait_confirm 状态, 如超时或收到 cancel 均回滚.

当然, TCC 也无法解决 confirm 成功的 actor 再也联系不上的问题. 联系不上只能通过可靠送达的 MQ 来解决, 如节点 confirm 后再也不开机了也就无可奈何了.

原文地址:https://www.cnblogs.com/inshua/p/13404727.html