[Java复习]分布式事务 TCC RocketMQ最终一致性

画一下你们电商系统的核心交易链路图,说说分布式架构下存在什么问题?

主要核心是要考虑分布式事务分布式锁的问题。

分布式系统,事务 -> 分布式事务,锁 -> 分布式锁

电商核心流程:

订单服务 -> 创建订单 -> 库存服务 -> 扣减库存 -> 积分服务 -> 增加积分 -> 仓储服务 -> 通知发货

针对电商核心交易链路,你们是怎么设计分布式事务技术方案的?

TCC可靠消息最终一致性方案是在生产中最常用。

一个要求强一致,一个要求最终一致。

强一致主要用于核心模块,例如交易/订单等。最终一致一般用于边缘模块例如库存,通过mq去通知,保证最终一致性,也可以业务解耦。

TCC:

订单服务、库存服务、积分服务 -> 绑定为一个TCC事务

撤销刚才创建订单时,回滚刚才扣减库存和增加积分

可靠消息最终一致性:

可以去发送一个请求给消息中间件,由中间件保证一定会把消息交给下游的库存服务去扣减库存,仓储服务去通知发货等,

如果这个过程中有消息发送失败,则可靠消息中间件应该保证不停的重试投递消息。

对于TCC事务、最终一致性事务的技术选型,你们是怎么做的?如何调研的?

TCC:

阿里开源了分布式事务框架,fescar,seata。seata类似TCC事务,经历过阿里生产环境大量考验的框架。支持Dubbo,Spring Cloud。

可靠消息最终一致性:

基于ActiveMQ,RabbitMQ, RocketMQ等,自己开发一个可靠消息服务,收到消息之后,尝试投递到MQ,如果投递失败,重试投递。

现在大量用RocketMQ,作为MQ中间件,提供了分布式事务支持,已经把可靠消息服务需要实现的功能逻辑已经做好了。

 

在搭建好的电商系统里,落地开发对交易链路的TCC分布式事务方案?

seata:特点:自动回滚数据库事务。

https://github.com/seata/seata-samples.git

把seata所有的示例代码拷贝下来,里面提供的例子就是跟我们说的电商的核心例子是类似的.

然后先要下载一个seata-server到本地,在这里下载:https://github.com/seata/seata/releases,

然后启动起来,这是分布式事务管理中心,负责维护每一个分布式事务的状态,触发分布式事务的提交和回滚。

    

你能说说一个TCC分布式事务框架的核心架构原理吗?

Seata架构原理:

https://github.com/seata/seata

Seata中角色:

Transaction Coordinator(TC):协调器,单独的一个server。维护全局和分支事务的状态,驱动全局事务的提交或回滚。

Transaction Manager(TM):全局事务的发起者,负责开始/提交/回滚一个全局事务。(对应订单服务)

Resource Manager(RM):管理分支事务(注册分支事务/状态/提交/回滚),并负责与TC通讯。

整个使用seata进行分布式事务管理的生命周期

1、TM向TC发起全局事务,TC返回XID作为标识。

2、XID通过调用链传播。

3、RM将本地的事务注册到TC中表示为XID的全局事务中,成为一个分支事务。

4、再由TM向TC请求标识为XID的全局事务提交/回滚。

5、最终,由TC去驱动所有的分支事务提交/回滚。

现有的TCC事务方案的性能瓶颈在哪里?能支撑高并发交易场景吗?如何优化?

使用分布式事务主要是保证核心链路要么全部成功,要么全部失败。当然也会带来一些性能的开销。

seata模型里面频繁的网络通信,以及对应事务的状态持久化的IO等等。

如果需要支撑高并发,那么TC服务也需要横向扩容。相应的,对于TC背后的DB也需要进行优化。

RocketMQ分布式事务:

你了解RocketMQ对分布式事务支持的底层实现原理吗?

核心链路使用seata这种类似于TCC的事务,而像wms这种相当于是分支链路,可以通过MQ进行解耦。

但是通过MQ解耦也会带来一些问题,例如消息丢失,消息重复等等问题,因此也需要进行最终一致性的保证。

  

 结合整个订单接口服务,分为两个支付链路,一个是核心链路(订单业务),一个是非核心链路(wms) 整个流程。

先向RocketMQ发送half msg,然后调用核心链路。核心链路要是返回失败,就会走失败的逻辑:退款,更改订单状态为取消,再给rocketmq发送callback废弃掉刚才的消息。

如果成功,就commit msg让消费者可以消费。如果在等待期间,一直没有callback/commit那么mq就会走回调查询具体的状态。最终消费者接收到消息后,消费完成就回复mq一个ack, 如果消费失败了,mq就会重新投递或者换一个服务投递。使用rocketmq的half msg机制,可以实现这一套固定模式的最终一致性,很完善。 这个将wms的操作放在核心链路前面的这个问题,是为了提升整个订单接口服务的效率,因为需要保证最终一致性,那么必然会有消息生产者对MQ的一些操作,包括重试,ack等等,如果将这些逻辑全部都放在核心链路执行完成后再去一一完成,那么可能会耗费一些时间。而通过rocketmq这个模式,可以通过half msg的支持,来将整个与mq的交互过程拆解掉,从而提升效率。

  

如果公司没有RocketMQ中间件,那你们如何实现最终一致性事务?

基于数据库自己开发一个可靠消息服务。接受上游Producer发送的haf msg, 存入DB,返回响应。本地可靠消息服务启动定时扫描本地DB的half msg,超过一定时间没有commit/rollback就回调Producer接口,确认本地事务是否成功,获取commit/rollback。如果消息commit就发送消息给下游服务或者发给RabbitMQ/Kafka/ActiveMQ,下游服务消费后,回调可靠消息服务接口进行ack,如果没有收到ack,重发消息给下游服务。

原文地址:https://www.cnblogs.com/fyql/p/12186296.html