分布式事务的理解

分布式事务结合应用场景更方便理解

场景

充值案列-用户缴费-订单中心收到费用,转到充值系统充值-充值系统接受到命令进行充值

假设一下如果用户缴费后,程序实现了扣费,这时订单中心挂掉,充值系统并未工作.用户扣费但是系统并没有充值.

解决方案-二阶提交协议(2PC)和三阶(3PC)提交协议

白话说就是在几个服务器之间引入一个事物中间件进行管理

每个服务器的本地事物执行之后返回中间件,由中间件进行统一的commit的提交

2PC参与者都事物阻塞

2PC中间件故障,其他参与者同样也处于事物阻塞

2PC在commit之后有参与者宕机无人知道事物是否提交

这里引入3PC

引入超时机制,3PC把2PC的准备阶段再次一分为二,这样三阶段提交就有CanCommit、PreCommit、DoCommit三个阶段。

在CanCommit,PreCommit如果是有信息中断会回滚事物,DoCommit阶段会继续执行,因为确认前阶段都已经接受到了返回的数据.

具体参考-http://blog.jobbole.com/95632/

解决方案-MQ事物处理

需要根据不同的业务设计做不同的应对

场景1-库存数量与订单数量一致性,采用补偿型+最大努力通知型,采用原因为不涉及跨机房和长事务(正常情况下库存与订单服务处理很快):

场景2-订单信息、支付信息、充值信息三者之间的一致性,采用异步确保型的原因是,整个业务链路太长且跨不同的机房系统,网络延迟较高,业务方面恰好不需要非常高的实时性,所以采用小事务+异步通知,目前正常情况下用户从下单到完成支付到流量到账平均为1-5分钟左右

场景3-直充到账后的消息通知(APP消息推送或短信通知),采用最大努力通知型,这个业务场景比较简单,在直充成功后,订单状态流转为已完成,此时通过消息服务进行到账通知业务的解耦,调用消息服务失败的情况下,使用定时任务努力通知。

场景4-对账稽核,结算稽核,这个涉及参考文章的业务逻辑,核对多组信息之后进行同步提交

参考文章为-http://blog.jobbole.com/110805/?from=singlemessage

业务实现逻辑

消息生产方,需要额外建一个消息表,并记录消息发送状态。消息表和业务数据要在一个事务里提交。实现时为了简单,可以只是增加一个字段。新增字段会跟业务强耦合,新增表处理起来不同交易数据可以通用处理。不过因为消息表跟业务需要在一个事务里,所以存储耦合在所难免。

消息消费方,需要处理这个消息,并完成自己的业务逻辑。此时如果本地事务处理成功,那发送给生产方一个confirm消息,表明已经处理成功了。如果处理失败,该消息还是需要放回MQ的。如果MQ支持重试,那就省事儿了。如果不支持,可以考虑把该消息放回队尾或另建一个队列特殊处理。当然非要处理成功才能继续,那只能block在这条消息了(估计一般人不会这么做)。Kafka lowlevel接口是支持自己设置offset的,所以可以实现block。

生产方定时扫描本地消息表,把还没处理完成的消息由发送一遍。如果有靠谱的自动对账补账逻辑,其实这一步也可以省略。在实践中,丢消息或者下游处理失败这种场景还是非常少的。这里要看业务上能不能容忍不一致到一个对账补账周期。

参考思路-https://zhuanlan.zhihu.com/p/25933039

分布式事物MQ注意事项-http://www.jianshu.com/p/716d3ec567c0

简单解释事物MQ-

http://www.infoq.com/cn/articles/solution-of-distributed-system-transaction-consistency

你可能感兴趣的:(分布式事务的理解)