【BUG事务内消息发送】事务内消息发送,事务还未结束,消息发送已被消费,查无数据怎么解决?

问题描述

在一个事务内完成插入操作,通过MQ异步通知其他微服务进行事件处理。

由于是在事务内发送,其他服务消费消息,查询数据时还不存在如何解决呢?


解决方案

通过spring-tx包的TransactionSynchronizationManager事务管理器解决。

java 复制代码
public abstract class TransactionSynchronizationManager {

	private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
			new NamedThreadLocal<>("Transaction synchronizations");

	/**
	 * Return if transaction synchronization is active for the current thread.
	 * Can be called before register to avoid unnecessary instance creation.
	 * @see #registerSynchronization
	 */		
	public static boolean isSynchronizationActive() {
		return (synchronizations.get() != null);
	}

	
	/**
	 * Register a new transaction synchronization for the current thread.
	 * Typically called by resource management code.
	 * <p>Note that synchronizations can implement the
	 * {@link org.springframework.core.Ordered} interface.
	 * They will be executed in an order according to their order value (if any).
	 * @param synchronization the synchronization object to register
	 * @throws IllegalStateException if transaction synchronization is not active
	 * @see org.springframework.core.Ordered
	 */
	public static void registerSynchronization(TransactionSynchronization synchronization)
			throws IllegalStateException {

		Assert.notNull(synchronization, "TransactionSynchronization must not be null");
		Set<TransactionSynchronization> synchs = synchronizations.get();
		if (synchs == null) {
			throw new IllegalStateException("Transaction synchronization is not active");
		}
		synchs.add(synchronization);
	}
	
}

Rocketmq方法封装,通过TransactionSynchronizationManager.isSynchronizationActive()判断当前方法的调用是否在事务内。

如果是,则注册一个事务同步适配器,在事务提交后发送消息。

否则直接发送。

java 复制代码
    /**
     * 事务内发送 mq时使用,强制到事务结束后发送
     */
    public SendResult sendAfterTrans(String topic, String tag, String key, String body) {
        final SendResult[] res = new SendResult[1];
        try {
            // 是否开启事务判断
            if (TransactionSynchronizationManager.isSynchronizationActive()) {
                log.debug("Mysql事务内Mq消息发送  延迟到事务提交后 waiting......");
                TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
                    @Override
                    public void afterCommit() {
                        log.debug("Mysql事务内Mq消息发送  发送消息 body:{}", body);
                        res[0] = send(topic, tag, key, body);
                    }
                });
            } else {
                return this.send(topic, tag, key, body);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return res[0];
    }
相关推荐
笨手笨脚の34 分钟前
设计模式-迭代器模式
java·设计模式·迭代器模式·行为型设计模式
spencer_tseng1 小时前
Eclipse 4.7 ADT (Android Development Tools For Eclipse)
android·java·eclipse
海奥华21 小时前
SQLEXPLAIN 详解
数据库·mysql
情深不寿3172 小时前
MySQL————数据库基础
数据库·mysql
聪明的笨猪猪2 小时前
Java Spring “AOP” 面试清单(含超通俗生活案例与深度理解)
java·经验分享·笔记·面试
程序新视界2 小时前
如何选择合适的数据库?PostgreSQL与MySQL各项对比
数据库·mysql·postgresql
seven97_top3 小时前
Springboot 常见面试题汇总
java·spring boot·后端
小蕾Java3 小时前
Java 开发工具,最新2025 IDEA 使用,保姆级教程
java·开发语言·intellij-idea
刘登辉3 小时前
idea使用联网缓存的pom进行离线开发
java·ide·intellij-idea·离线开发
Автомата Калашникова3 小时前
Java操作.docx文档 —— docx4j
java·开发语言