个人物联网项目(十四) 分布式事务

2.0平台服务化架构,必然分库,分库又必然面临一个分布式事务处理问题,因此不管是设计仍是编码远远比1.0单体应用架构的工做量要大。不过作任何事情,重点不在实施,而是在思路,因此要解决分布式事务问题,还得先想清楚屡清楚怎么去作才是重点之重。spring

分布式事务处理方法其实大把,无需担心找不到解决方法,关键是要找到知足本身业务场景,适合本身业务场景的方法,我以前作的项目涉及个分布式事务处理的方法也有好几个,其中记忆较为清晰的是一个移动充值的业务,大概业务就是用户经过银行在线支付完成后,而后给本身的手机号码充值,这个里面就涉及到银行充值和手机话费充值两个一致性的事务,当初用的就是经过天天凌晨的对帐来处理这种事务问题,实现思路就是手机话费充值这端天天凌晨会上传一个订单文件到一个FTP服务器,而后通知银行那边去拿这个对帐单文件来对帐,而后再实行差补各类结算。固然具体问题还得具体分析,若是咱们如今的业务场景直接也生搬硬套用这种方式来处理会不会也行呢?确定不行!数据库

咱们的业务场景流程:用户经过APP扫码摇摇车,消费1块钱,针对每条订单立刻全部参与方进行算帐。服务器

1. 用户帐户扣1块钱。网络

2. 平台分2毛钱。架构

3. 城市合伙人帐户分4毛钱。异步

4. 商家帐户分4毛钱。分布式

备注:前面在2.0架构体系里面已经说过度库分红用户库,平台库,城市合伙人库,商家库。微服务

因此像这种业务场景,咱们这边目前采用的是基于日志(事件)的最终一致性来实现分布式事务,固然里面涉及到知识点也较多,包括数据库单机事务,MQ消息通知,定时调度,异步等。优化

在详细介绍基于日志(事件)的最终一致性以前,必须先稍微说下柔性事务和刚性事务,其实这些概念没那么复杂,所谓的刚性事务是指严格遵循ACID原则的事务, 例如单机环境下的数据库事务,就是以前咱们1.0平台spring事务实现那种。柔性事务稍微复杂点,是指遵循BASE理论的事务, 常见的实现方式有不少种: 两阶段提交(2PC),TCC补偿型提交,基于消息的异步确保型,最大努力通知型等。编码

我说这么多其实就是想说:大事务=小事务(原子事务)+异步(消息通知)。

这个里面每一个库里面都有两个事件表,eventPublish(待发布事件表)和eventProcess(待处理事件表),表设计以下,也能够针对本身业务场景具体设计。

好啦,举个简单例子,APP扫码启动摇摇车(涉及两个微服务)。

1. 用户减小资金(数据库A)

2. 商家增长资金(数据库B)

基于日志(事件)的最终一致性实现思路以下:

1.用户服务在接收到用户请求后开启事务, 减小资金, 而且在eventPublish表建立一条status为1(待发布)的记录, payload记录的是事件内容, 提交事务。

2.用户服务中的定时器扫描,方法里面开启事务, 而后查询eventPublish是否有status为1的记录,查询到记录以后,拿到payload信息,经过MQ将消息发布商家(商家端有MQ实时监听)。

3.商家服务监听到MQ传来的用户减小资金事件(先判断下数据库是否已经存在,若是存在,经过MQ发消息给用户,向用户端返回接收成功的消息), 在eventProcess表建立一条status为1(待处理)的记录,payload记录的是事件内容, 若是保存成功, 向用户端(用户端有MQ实时监听)返回接收成功的消息。(目的是用户端将eventPublish的status为2,下次扫描就不会扫描到了)

4.用户端监听到接收成功后的消息,将eventPublish的status为2(已发布),下次扫描就不会扫描到了,要否则会持续往商家那边发消息,告诉商家那边增长资金。

5.商家服务中的定时器扫描,方法里面开启事务, 而后查询eventProcess是否有status为1(待处理)的记录,查询到记录以后, 拿到payload信息,处理业务给商家增长资金. 处理成功以后修改数据库中eventProcess的status为2(已完成),,最后提交事务。

大概实现思路就是这样,这种处理方式网络请求吞吐量是比较高的,基本都是分段式异步处理的。

 

固然咱们的业务场景比这个更加复杂些,一个流程涉及到的原子库更多,可是大概的思路都是相似处理,整个设计以下:

咱们的具体业务状况整个流程还有两块也在优化中。

1.异常容灾处理,好比分段式进入到中间某段因为各类缘由没法进行下一步,并且接二连三经过MQ和调度在执行屡次,这个时候咱们会检测,若是尝试重试屡次无效,会进入到二级消息队列,并能够后台人工参与处理。

2.单链路方式的灵活性再增强,好比用户的下一段并非到商家,也有多是城市合伙人,或者其它,这个时候能够经过MQ的传递参数进行判断,下一段的到达点。

总之基于MQ分布式业务的处理场景,瓶颈稳定性在于MQ自己,因此这块必须保证它的持续高可用和稳定性,后续在项目中碰到的细节问题我会继续分享。