批量处理大型数据列表:实现事务性操作的策略

Don’t say much, just go to the code.

    /**
     * 对大型数据列表进行分批处理,并在每批数据上执行事务性处理
     *
     * @param sortedList                    已排序的数据列表,确保批处理的顺序性,减少死锁风险
     * @param batchSize                     每批处理的数据量大小
     * @param batchProcessorWithTransaction 用于处理每一批次数据并执行事务的函数,接收当前批次数据和重试次数
     * @author bood
     * @since 2024/01/23
     */
    public <T> void batchProcessOptimized(List<T> sortedList, int batchSize,
                                          BiConsumer<List<T>, Integer> batchProcessorWithTransaction) {
        int startIdx = 0;
        while (startIdx < sortedList.size()) {
            int endIdx = Math.min(sortedList.size(), startIdx + batchSize);
            List<T> batch = sortedList.subList(startIdx, endIdx);
            boolean isProcessedSuccessfully = false;
            int retryCount = 0;
            while (!isProcessedSuccessfully && retryCount < 3) {
                try {
                    batchProcessorWithTransaction.accept(batch, retryCount);
                    isProcessedSuccessfully = true;
                } catch (DataAccessException ex) {
                    if (isDeadlockException(ex)) {
                        retryCount++;
                        waitForRetry(retryCount);
                    } else {
                        throw ex;
                    }
                }
            }
            startIdx = endIdx;
        }
    }

    /**
     * 检查是否因为数据库死锁导致的异常
     *
     * @param ex 异常对象
     * @return boolean
     * @author bood
     * @since 2024/01/23
     */
    private boolean isDeadlockException(DataAccessException ex) {
        Throwable cause = ex.getCause();
        return cause instanceof SQLException && "40001".equals(((SQLException) cause).getSQLState());
    }

    /**
     * 根据重试次数进行等待,采用指数退避策略减少连续死锁的可能性
     *
     * @param retryCount 当前重试次数
     * @author bood
     * @since 2024/01/23
     */
    private void waitForRetry(int retryCount) {
        try {
            long waitTimeMillis = (long) (Math.pow(2, retryCount) * 100);
            Thread.sleep(waitTimeMillis);
        } catch (InterruptedException ie) {
            Thread.currentThread().interrupt();
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值