在springboot中如何保证主线程的事务和子线程的事务一致性

126 阅读6分钟

在springboot中如何保证主线程的事务和子线程的事务一致性

import cn.hutool.core.thread.NamedThreadFactory;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;

/**
 * 多线程处理事务,并且保持事务一致性
 */
@Service
@Slf4j
public class HandleTsMoreThreadService {

    @Autowired
    private DataSourceTransactionManager transactionManager;


    private static final ExecutorService TsMoreThreadExecutePool = new ThreadPoolExecutor(4, 64,
            0L, TimeUnit.MILLISECONDS,
            new SynchronousQueue<>(), new NamedThreadFactory("TsMoreThreadExecute-Pool", false),
            new ThreadPoolExecutor.AbortPolicy());


    /**
     * 执行多个事务(不区分主要事务和子事务的执行顺序)
     *
     * @param mainTask 主线程任务
     * @param subTasks 子线程任务列表
     * @param timeoutSeconds 超时时间(秒)
     * @return 是否全部成功
     */
    public boolean executeDistributedTransaction(
            Runnable mainTask,
            List<Runnable> subTasks,
            long timeoutSeconds) {

        // 用于协调所有线程完成
        CountDownLatch completeLatch = new CountDownLatch(subTasks.size() + 1);

        // 用于协调事务提交
        CountDownLatch commitLatch = new CountDownLatch(1);

        // 标记是否有任何线程失败
        AtomicBoolean hasError = new AtomicBoolean(false);

        // 存储所有事务状态
        List<TransactionStatus> transactionStatuses = new java.util.concurrent.CopyOnWriteArrayList<>();

        try {
            // 1. 启动主线程事务
            executeMainTransaction(mainTask, completeLatch, commitLatch, hasError, transactionStatuses);

            // 2. 启动子线程事务
            executeSubTransactions(subTasks, completeLatch, commitLatch, hasError, transactionStatuses);

            // 3. 等待所有线程完成业务逻辑
            boolean allCompleted = completeLatch.await(timeoutSeconds, TimeUnit.SECONDS);

            if (!allCompleted) {
                log.error("事务执行超时,开始回滚所有事务");
                hasError.set(true);
            }

            // 4. 根据执行结果决定提交还是回滚
            if (hasError.get()) {
                log.info("检测到错误,开始回滚所有事务");
                rollbackAllTransactions(transactionStatuses);
                return false;
            } else {
                log.info("所有线程执行成功,开始提交所有事务");
                commitLatch.countDown(); // 通知所有线程可以提交
                commitAllTransactions(transactionStatuses);
                return true;
            }

        } catch (Exception e) {
            log.error("分布式事务执行异常", e);
            hasError.set(true);
            rollbackAllTransactions(transactionStatuses);
            return false;
        }
    }

    /**
     * 执行主线程事务
     */
    private void executeMainTransaction(
            Runnable mainTask,
            CountDownLatch completeLatch,
            CountDownLatch commitLatch,
            AtomicBoolean hasError,
            List<TransactionStatus> transactionStatuses) {

        Thread mainThread = new Thread(() -> {
            TransactionStatus status = null;
            try {
                // 开启事务
                DefaultTransactionDefinition def = new DefaultTransactionDefinition();
                def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
                def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
                status = transactionManager.getTransaction(def);

                log.info("主线程事务开始执行,线程ID: {}", Thread.currentThread().getId());

                // 执行业务逻辑
                mainTask.run();

                log.info("主线程业务逻辑执行完成");
                completeLatch.countDown();

                // 等待协调器通知是否提交
                boolean shouldCommit = commitLatch.await(300, TimeUnit.SECONDS);

                if (shouldCommit && !hasError.get()) {
                    transactionManager.commit(status);
                    log.info("主线程事务提交成功");
                } else {
                    transactionManager.rollback(status);
                    log.info("主线程事务回滚完成");
                }
            } catch (Exception e) {
                log.error("主线程执行异常", e);
                hasError.set(true);
                completeLatch.countDown();
                if (status != null && !status.isCompleted()) {
                    transactionManager.rollback(status);
                }
            } finally {
                transactionStatuses.add(status);
            }
        });
        mainThread.setName("MainTransactionThread");
        mainThread.start();
    }

    /**
     * 执行子线程事务
     */
    private void executeSubTransactions(
            List<Runnable> subTasks,
            CountDownLatch completeLatch,
            CountDownLatch commitLatch,
            AtomicBoolean hasError,
            List<TransactionStatus> transactionStatuses) {

        for (int i = 0; i < subTasks.size(); i++) {
            final int taskIndex = i;
            final Runnable task = subTasks.get(i);

            TsMoreThreadExecutePool.execute(() -> {
                TransactionStatus status = null;
                try {
                    // 开启新事务
                    DefaultTransactionDefinition def = new DefaultTransactionDefinition();
                    def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
                    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
                    status = transactionManager.getTransaction(def);

                    log.info("子线程{}事务开始执行,线程ID: {}", taskIndex, Thread.currentThread().getId());

                    // 执行业务逻辑
                    task.run();

                    log.info("子线程{}业务逻辑执行完成", taskIndex);
                    completeLatch.countDown();

                    // 等待协调器通知是否提交
                    boolean shouldCommit = commitLatch.await(300, TimeUnit.SECONDS);

                    if (shouldCommit && !hasError.get()) {
                        transactionManager.commit(status);
                        log.info("子线程{}事务提交成功", taskIndex);
                    } else {
                        transactionManager.rollback(status);
                        log.info("子线程{}事务回滚完成", taskIndex);
                    }

                } catch (Exception e) {
                    log.error("子线程{}执行异常", taskIndex, e);
                    hasError.set(true);
                    completeLatch.countDown();
                    if (status != null && !status.isCompleted()) {
                        transactionManager.rollback(status);
                    }
                } finally {
                    transactionStatuses.add(status);
                }
            });
        }
    }

    /**
     * 提交所有事务
     */
    private void commitAllTransactions(List<TransactionStatus> transactionStatuses) {
        for (TransactionStatus status : transactionStatuses) {
            try {
                if (!status.isCompleted()) {
                    transactionManager.commit(status);
                }
            } catch (Exception e) {
                log.error("提交事务失败", e);
            }
        }
    }

    /**
     * 回滚所有事务
     */
    private void rollbackAllTransactions(List<TransactionStatus> transactionStatuses) {
        for (TransactionStatus status : transactionStatuses) {
            try {
                if (!status.isCompleted()) {
                    transactionManager.rollback(status);
                }
            } catch (Exception e) {
                log.error("回滚事务失败", e);
            }
        }
    }


    /**
     * 顺序执行分布式事务(主事务完成后子事务才执行)
     *
     * @param mainTask 主线程任务
     * @param subTasks 子线程任务列表
     * @param timeoutSeconds 超时时间(秒)
     * @return 是否全部成功
     */
    public boolean executeSequentialTransaction(
            Runnable mainTask,
            List<Runnable> subTasks,
            long timeoutSeconds) {

        // 主事务完成信号
        CountDownLatch mainTaskCompleteLatch = new CountDownLatch(1);

        // 所有子事务完成信号
        CountDownLatch subTasksCompleteLatch = new CountDownLatch(subTasks.size());

        // 提交信号
        CountDownLatch commitLatch = new CountDownLatch(1);

        // 全局错误标记
        AtomicBoolean hasError = new AtomicBoolean(false);

        // 主事务状态
        AtomicReference<TransactionStatus> mainTransactionStatus = new AtomicReference<>();

        // 子事务状态集合
        List<TransactionStatus> subTransactionStatuses = new java.util.concurrent.CopyOnWriteArrayList<>();

        try {
            log.info("开始执行顺序分布式事务,主事务优先执行");

            // 1. 启动主事务
            executeMainTransactionSequential(
                    mainTask,
                    mainTaskCompleteLatch,
                    commitLatch,
                    hasError,
                    mainTransactionStatus
            );

            // 2. 等待主事务完成
            boolean mainCompleted = mainTaskCompleteLatch.await(timeoutSeconds / 2, TimeUnit.SECONDS);

            if (!mainCompleted) {
                log.error("主事务执行超时");
                hasError.set(true);
                return false;
            }

            if (hasError.get()) {
                log.error("主事务执行失败,跳过子事务执行");
                rollbackMainTransaction(mainTransactionStatus.get());
                return false;
            }

            log.info("主事务执行完成,开始执行子事务");

            // 3. 主事务完成后,启动子事务
            executeSubTransactionsSequential(
                    subTasks,
                    subTasksCompleteLatch,
                    commitLatch,
                    hasError,
                    subTransactionStatuses
            );

            // 4. 等待所有子事务完成
            boolean subCompleted = subTasksCompleteLatch.await(timeoutSeconds / 2, TimeUnit.SECONDS);

            if (!subCompleted) {
                log.error("子事务执行超时");
                hasError.set(true);
            }

            // 5. 根据执行结果决定提交还是回滚
            if (hasError.get()) {
                log.info("检测到错误,开始回滚所有事务");
                rollbackAllTransactions(mainTransactionStatus.get(), subTransactionStatuses);
                return false;
            } else {
                log.info("所有事务执行成功,开始统一提交");
                commitLatch.countDown(); // 通知所有事务可以提交
                commitAllTransactions(mainTransactionStatus.get(), subTransactionStatuses);
                return true;
            }

        } catch (Exception e) {
            log.error("顺序分布式事务执行异常", e);
            hasError.set(true);
            rollbackAllTransactions(mainTransactionStatus.get(), subTransactionStatuses);
            return false;
        }
    }

    /**
     * 执行主事务(顺序模式)
     */
    private void executeMainTransactionSequential(
            Runnable mainTask,
            CountDownLatch mainTaskCompleteLatch,
            CountDownLatch commitLatch,
            AtomicBoolean hasError,
            AtomicReference<TransactionStatus> mainTransactionStatus) {

        Thread mainThread = new Thread(() -> {
            TransactionStatus status = null;
            try {
                // 开启主事务
                DefaultTransactionDefinition def = new DefaultTransactionDefinition();
                def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
                def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
                def.setTimeout(300); // 5分钟超时

                status = transactionManager.getTransaction(def);

                log.info("主事务开始执行,线程ID: {}, 事务名称: {}",
                        Thread.currentThread().getId(),
                        Thread.currentThread().getName());

                // 执行主业务逻辑
                mainTask.run();

                log.info("主事务业务逻辑执行完成,通知子事务开始执行");

                // 通知主事务完成,子事务可以开始
                mainTaskCompleteLatch.countDown();

                // 等待协调器通知是否提交
                boolean shouldCommit = commitLatch.await(300, TimeUnit.SECONDS);

                if (shouldCommit && !hasError.get()) {
                    transactionManager.commit(status);
                    log.info("主事务提交成功");
                } else {
                    transactionManager.rollback(status);
                    log.info("主事务回滚完成");
                }

            } catch (Exception e) {
                log.error("主事务执行异常", e);
                hasError.set(true);

                // 通知主事务完成(即使失败也要通知,避免死锁)
                mainTaskCompleteLatch.countDown();

                if (status != null && !status.isCompleted()) {
                    try {
                        transactionManager.rollback(status);
                    } catch (Exception rollbackEx) {
                        log.error("主事务回滚异常", rollbackEx);
                    }
                }
            } finally {
                mainTransactionStatus.set(status);
            }
        });

        mainThread.setName("MainSequentialTransactionThread");
        mainThread.start();
    }

    /**
     * 执行子事务(在主事务完成后)
     */
    private void executeSubTransactionsSequential(
            List<Runnable> subTasks,
            CountDownLatch subTasksCompleteLatch,
            CountDownLatch commitLatch,
            AtomicBoolean hasError,
            List<TransactionStatus> subTransactionStatuses) {

        for (int i = 0; i < subTasks.size(); i++) {
            final int taskIndex = i;
            final Runnable task = subTasks.get(i);

            TsMoreThreadExecutePool.execute(() -> {
                TransactionStatus status = null;
                try {
                    // 开启独立子事务
                    DefaultTransactionDefinition def = new DefaultTransactionDefinition();
                    def.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
                    def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
                    def.setTimeout(300); // 5分钟超时

                    status = transactionManager.getTransaction(def);

                    log.info("子事务{}开始执行,线程ID: {}, 线程名称: {}",
                            taskIndex,
                            Thread.currentThread().getId(),
                            Thread.currentThread().getName());

                    // 执行子业务逻辑
                    task.run();

                    log.info("子事务{}业务逻辑执行完成", taskIndex);

                    // 通知子事务完成
                    subTasksCompleteLatch.countDown();

                    // 等待协调器通知是否提交
                    boolean shouldCommit = commitLatch.await(300, TimeUnit.SECONDS);

                    if (shouldCommit && !hasError.get()) {
                        transactionManager.commit(status);
                        log.info("子事务{}提交成功", taskIndex);
                    } else {
                        transactionManager.rollback(status);
                        log.info("子事务{}回滚完成", taskIndex);
                    }

                } catch (Exception e) {
                    log.error("子事务{}执行异常", taskIndex, e);
                    hasError.set(true);

                    // 即使异常也要通知完成,避免死锁
                    subTasksCompleteLatch.countDown();

                    if (status != null && !status.isCompleted()) {
                        try {
                            transactionManager.rollback(status);
                        } catch (Exception rollbackEx) {
                            log.error("子事务{}回滚异常", taskIndex, rollbackEx);
                        }
                    }
                } finally {
                    subTransactionStatuses.add(status);
                }
            });
        }
    }

    /**
     * 提交所有事务
     */
    private void commitAllTransactions(
            TransactionStatus mainStatus,
            List<TransactionStatus> subStatuses) {

        // 先提交子事务,后提交主事务
        for (int i = 0; i < subStatuses.size(); i++) {
            TransactionStatus status = subStatuses.get(i);
            try {
                if (status != null && !status.isCompleted()) {
                    transactionManager.commit(status);
                    log.info("子事务{}提交成功", i);
                }
            } catch (Exception e) {
                log.error("子事务{}提交失败", i, e);
            }
        }

        // 最后提交主事务
        try {
            if (mainStatus != null && !mainStatus.isCompleted()) {
                transactionManager.commit(mainStatus);
                log.info("主事务提交成功");
            }
        } catch (Exception e) {
            log.error("主事务提交失败", e);
        }
    }

    /**
     * 回滚所有事务
     */
    private void rollbackAllTransactions(
            TransactionStatus mainStatus,
            List<TransactionStatus> subStatuses) {

        // 先回滚子事务
        for (int i = 0; i < subStatuses.size(); i++) {
            TransactionStatus status = subStatuses.get(i);
            try {
                if (status != null && !status.isCompleted()) {
                    transactionManager.rollback(status);
                    log.info("子事务{}回滚成功", i);
                }
            } catch (Exception e) {
                log.error("子事务{}回滚失败", i, e);
            }
        }

        // 再回滚主事务
        rollbackMainTransaction(mainStatus);
    }

    /**
     * 回滚主事务
     */
    private void rollbackMainTransaction(TransactionStatus mainStatus) {
        try {
            if (mainStatus != null && !mainStatus.isCompleted()) {
                transactionManager.rollback(mainStatus);
                log.info("主事务回滚成功");
            }
        } catch (Exception e) {
            log.error("主事务回滚失败", e);
        }
    }
    // 测试例子
    public  void test () {
        Runnable mainTask = () -> {
            try {
                log.info("主线程:开始保存寻源需求主表数据");
                // 填充业务逻辑
            } catch (Exception e) {
                log.error("主线程执行失败", e);
                //throw new BizException (e);
            }
        };
        // 子线程任务列表
        java.util.List<Runnable> subTasks = Arrays.asList(
                // 子任务1
                () -> {
                    try {
                        log.info("执行子任务1");
                        // 填充业务逻辑
                    } catch (Exception e) {
                        log.error("子线程1执行失败", e);
                        //throw new BizException(e);
                    }
                },

                // 子任务2
                () -> {
                    try {
                        log.info("执行子任务2");
                        // 填充业务逻辑
                    } catch (Exception e) {
                        log.error("子线程2执行失败", e);
                        //throw new BizException(e);
                    }
                }
        );
        //执行分布式事务
        boolean success = executeSequentialTransaction(
                mainTask,
                subTasks,
                600 // 600秒超时
        );
        if (success) {
            log.info("测试完成:所有事务提交成功");
        } else {
            log.error("测试完成:事务执行失败,已回滚");
        }
    }
}