在分布式的场景下,我们经常能遇到事务一致性问题,如何去保证事务的一致性,是分布式场景下不可避免的一个重要话题。
我们很难去做到事务的强一致性(有方案),因此会退一步去保证事务的最终一致性。
如何去保证事务的最终一致性呢?我们可以利用RocketMQ的事务消息来保证事务的最终一致性。
RocketMQ如何保证事务的一致性呢?原来,RocketMQ通过将应用本地事务和发送消息操作定义到全局事务中,要么同时成功,要么同时失败。这样就保证了本地事务和消息发送的一致性:

事务消息的原理可以参考事务消息以及收发事务消息,接下来我们需要将其应用到我们的SpringBoot应用中去。
首先引入RocketMQ的starter依赖(gradle):
//省略其他依赖
implementation 'org.apache.rocketmq:rocketmq-spring-boot-stater:2.2.0'
rocketmq-spring-boot-stater提供了Spring环境下的RocketMQ的集成,它使RocketMQ使用起来更加的方便。不同于上述的收发事务消息里的实现,我们可以通过实现RocketMQLocalTransactionListener来简化我们的操作。然后可以可以通过TransactionMQProducer#sendMessageInTransaction来发送消息
通过上述的操作,最终所有的回调都会进入RocketMQLocalTransactionListener#executeLocalTransaction这个方法。然而这样的话,我们如何去做不同的业务,然后提交事务呢?我们注意到sendMessageInTransaction方法的第二个参数是一直透传到executeLocalTransaction方法的第二个参数的,这个参数的作用RocketMQ的解释是与本地事务执行器一起使用的参数,因此我们可以利用这个参数来实现业务操作。
我们设计一个本地事务执行器,将这个执行器作为sendMessageInTransaction的第二个参数,然后就可以在executeLocalTransaction方法里面执行执行器的操作了:
public interface LocalTransactionExecutor<R> {
/**
* 执行本地业务并提交事务
* @author zhaosheng
*/
void execute();
/**
* 返回结果或抛异常
* @author zhaosheng
*/
R getResult() throws Exception;
}
然后提供一个默认的实现:
public class DefaultLocalTransactionExecutor<R> implements LocalTransactionExecutor<R> {
private MyException myException;
private Exception exception;
private R result;
private Runnable runnable;
private Supplier<R> supplier;
public DefaultLocalTransactionExecutor(Runnable runnable) {
this.runnable = runnable;
}
public DefaultLocalTransactionExecutor(Supplier<R> supplier) {
this.supplier = supplier;

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



