技术干货|分布式事务
微服务倡导将复杂的系统拆分为若干个简单、职责单一、松耦合的服务,可以降低开发难度,便于敏捷开发。而对大多数中小型公司来说,实施微服务架构面临以下困难:
- 单体应用拆分为分布式系统后,应用间的通讯和故障处理机制变得复杂
- 微服务化后,一个简单的功能需要调用多个服务并操作多个数据库实现,数据一致性难以保障
- 大量的微服务,导致其测试、维护、部署变得困难
基于二阶段提交的XA协议
- 第一阶段:协调者询问所有参与者是否可以执行提交操作,参与者执行准备工作,例如为资源上锁,预留资源,写undo/redo log。
- 第二阶段:若所有参与者回应“可提交”,则向所有参与者发送正式提交命令;若某个参与者回应“拒绝提交”,则向所有参与者发送回滚命令。
XA协议保障了事务的强一致性,然而由于其采用的阻塞协议带来的巨大性能开销,难以达到较高的系统吞吐量。
TCC模式
TCC提供了一种全局事务解决方案,业务系统只需实现下面三个操作,即可完成分布式事务:
- TRY:完成参与者业务检查并预留业务资源
- CONFIRM:使用TRY阶段的预留业务资源,并执行业务
- CANCEL:释放TRY结算预留的业务资源
TCC模式可以让业务更灵活地定义数据库操作的粒度,使得降低锁冲突、提高吞吐量成为可能,然而它对业务的侵入度较高,实现难度较大。
事务消息
通过消息的异步事务,可以保证本地事务和消息发送同时执行成功或失败,从而保证了数据的最终一致性。
- 发送prepare消息,该消息对Consumer不可见
- 执行本地事务
- 若本地事务执行成功,则向MQ提交消息确认发送指令;若本地事务执行失败,则向MQ发送取消指令
- 若MQ长时间未收到确认发送或取消发送的指令,则向业务系统询问本地事务状态,并做补偿处理
RocketMQ事务消息
客户端事务消息发送
发送prepare消息复用了普通消息发送,只是给消息增加了TRAN_MSG=true的属性,该属性决定prepare消息对Consumer不可见
消息写入CommitLog
事务消息的CommitLog写入和普通消息一致,它利用文件的顺序写来提升吞吐量,并采用文件映射的方式降低系统开销。
消息写入ConsumeQueue
ConsumeQueue的写入是采用异步方式完成的,ReputMessageSerivce作为一个长驻线程负责查询索引的构造和ConsumeQueue的写入,对于Prepare/Rollback消息不会写ConsumeQueue,从而保证它们对Consumer不可见
Broker端事务提交/回滚
Broker收到提交/回滚指令后,首先从根据offset从CommitLog读出原有的prepare消息,构造新的消息(修改事务状态标识)并写入Broker。对于一条事务消息,RocketMQ会存储两条消息,存在一定资源浪费。其实它是为了保证随后的消费者能尽可能从PageCache中读到该消息,而不是读取较早的prepare消息(可能导致缺页中断),以提升系统吞吐量。
此外,RocketMQ的最新版本(4.2.0)尚未支持本地事务的状态回查,这样可能存在由于网络抖动,导致commit/rollback未提交到broker导致prepare消息长期悬挂的风险。
在RocketMQ的设计文档中,为事务消息增加了一张事务状态表,它维护了消息的Offset、事务状态(P/C/R)信息。可以采用如下思路实现事务消息的回查机制:
- 在prepare消息写入commitLog后,可以通过CommitLogDispatcher写入一条事务状态记录(state=P)
- 在提交/回滚事务时,根据transactionId找到对应的事务状态记录,并修改对应的事务状态
- 通过长驻线程扫描事务状态表,对于超过一定时间的Prepare事务,发起对业务方的事务状态回查,根据回查结果修改事务状态,并向brokder发送相应的Commit/Rollback消息(其实在broker端,也就是服务端,有一个定时任务,它会按照配置的周期去定时扫描长时间没有得到回复的消息,然后通过TCP消息去询问客户端其本地事务的执行状态,客户端会有自定义业务逻辑去告诉服务端,服务端得到消息后会把消息拿到真正的topic中,这个时候消费端才会见到本次消息,才可以拉取这条事物消息)
- 最后一步就是消费端了,消费端一定要进行幂等逻辑的处理,不处理重复消息,即使消费成功了,但是因为网络原因回复失败了,broker端还是会有重复发消息发过来,这个时候幂等逻辑就起作用了,所以消费端要做好这方面处理。
[ShareSDK] 轻松实现社会化功能 强大的社交分享
[SMSSDK] 快速集成短信验证 联结通讯录社交圈
[MobLink] 打破App孤岛 实现Web与App无缝链接
[MobPush] 快速集成推送服务 应对多样化推送场景
[AnalySDK] 精准化行为分析 + 多维数据模型 + 匹配全网标签 + 垂直行业分析顾问
BBSSDK | ShareREC | MobAPI | MobPay | ShopSDK | MobIM | App工厂
截止2018 年4 月,Mob 开发者服务平台全球设备覆盖超过84 亿,SDK下载量超过3,300,000+次,服务超过380,000+款移动应用