分布式事务的完整架构图
案例场景分析
案例一:用RestTemplate演示(不可靠生产,会出现问题)
创建一个订单模块
创建一个OrderDataBaseService服务
创建一个order的service服务,调用saveOrder()方法
创建一个运单模块
创建一个运单的controller层,定义一个lock接口
创建一个运单的service层,定义一个dispatch()方法,用来controller调用
定义一个测试用例
运行成功之后数据库会保存数据
首先是运单表保存数据
订单表保存数据
现在就来模拟分布式事务产生的错误问题
模拟分布式事务问题:在订单模块OrderService里面的dispatchHttpApi()方法中使用RestTemplate远程调用接口,这里模拟一个连接超时的错误,定义的是连接时间不能超过3秒
接下来去运单模块的controller层的lock()接口中,让他睡眠3秒,来达到订单模块一个错误问题
使用这个测试用例
启动之后就会在订单服务出现一个错误
查看数据库,运单表数据正常
但是订单表没有保存数据 ,因为在订单服务出现读以超时的错误,在createOrder()方法上面定义了事务的注解,出现错误的时候,进行了回滚。
就此,分布式事务问题就此产生。
案例二:使用rabbitmq解决
在OrderDataBaseService服务中,添加一个saveLocalMessage()方法,是用来记录消息是否发送,通过status这个字段判断
创建一个MQOrderService服务
创建一个OrderMQService服其中regCallback()方法是用来判断消息是否发送到交换机(rabbitmq是消息到了交换机之后,交换机自动发送给对应的对列)
消费者在消费的过程中出现异常,rabbitmq会出现什么问题和解决方案:
rabbitmq会出现死循环,死循环会造成我们服务的重试,若是个集群,那么就会重试每个集群,会把我们服务器冲垮,把我们rabbitmq的磁盘、内存消耗殆尽,让我们程序宕机
解决办法:1、控制重发次数 2、try+catch+手动ack 3、try+catch+手动ack+死信队列+人工干预