gpt4 book ai didi

java - 如何对单个事务多次调用@Transactional方法

转载 作者:行者123 更新时间:2023-12-01 16:43:19 24 4
gpt4 key购买 nike

我有一个方法

@Transactional
public void updateSharedStateByCommunity(List[]idList)

此方法是从以下 REST API 调用的:

@RequestMapping(method = RequestMethod.POST)
public ret_type updateUser(param) {
// call updateSharedStateByCommunity
}

现在ID列表非常大,比如200000,当我尝试处理它时,需要很长时间并且在客户端发生超时错误。

因此,我想将其拆分为两个调用,每个调用的列表大小为 100000。

但是,问题是,它被视为两个独立的事务。

注意:2次调用只是一个例子,如果号码id更大的话,它可以分为多次。

我需要确保对单个事务进行两次单独的调用。如果这 2 个调用中的任何一个失败,那么它应该回滚到所有操作。

另外,在客户端,我们需要显示进度对话框,所以我不能只使用超时。

最佳答案

在我看来,对你的问题最明显的直接答案是稍微改变代码:

@RequestMapping(method = RequestMethod.POST)
public ret_type updateUser(param) {
updateSharedStateByCommunityBlocks(resolveIds);
}

...

And in Service introduce a new method (if you can't change the code of the service provide an intermediate class that you'll call from controller with the following functionality):

@Transactional
public updateSharedStatedByCommunityBlocks(resolveIds) {
List<String> [] blocks = split(resolveIds, 100000); // 100000 - bulk size
for(List<String> block :blocks) {
updateSharedStateByCommunity(block);
}
}

如果此方法位于同一个服务中,则原始 updateSharedStateByCommunity 中的 @Transactional 将不会执行任何操作,因此它会起作用。如果您将此代码放入其他类中,那么它将起作用,因为 spring 事务的默认传播级别是“必需”

因此它满足了苛刻的要求:您想要进行一次交易 - 您已经做到了。现在所有代码都在同一个事务中运行。现在每个方法都使用 100000 个 ID 运行,而不是使用所有 id,一切都是同步的:)

但是,由于许多不同的原因,这种设计存在问题。

  1. 它不允许跟踪进度(向用户显示),正如您在问题的最后一句中所说的那样。 REST 是同步的。

  2. 它假设网络是可靠的,并且等待 30 分钟在技术上不是问题(不考虑用户体验和必须等待的“紧张”用户:))

  3. 除此之外,网络设备还可以强制关闭连接(例如具有预先配置的请求超时的负载均衡器)。

这就是为什么人们建议某种异步流。

我可以说,您仍然可以使用异步流,生成任务,并在每次批量更新后一些共享状态(在单个实例的情况下在内存中)和持久状态(如集群情况下的数据库) .

这样与客户端的交互就会改变:

  1. 客户端使用 200000 个 ID 调用“updateUser”
  2. 服务会“立即”响应,例如“我收到了您的请求,这是一个请求 ID,请偶尔向我发送 ping 消息,看看会发生什么情况。
  3. 服务启动异步任务并在单个事务中逐 block 处理数据
  4. 客户端使用该 ID 调用“get”方法,服务器从共享状态读取进度。
  5. 准备就绪后,“Get”方法将响应“done”。

如果事务执行期间出现故障,则回滚完成,并且进程将数据库状态更新为“失败”。

您还可以使用更现代的技术来通知服务器(例如网络套接字),但这超出了这个问题的范围。

这里需要考虑的另一件事是:据我所知,处理 200000 个对象应该在不到 30 分钟的时间内完成,这对于现代 RDBMS 来说并不算多。当然,在不知道您的用例的情况下,很难判断那里发生了什么,但也许您可以优化流程本身(使用批量操作、减少对数据库的请求数量、缓存等)。

关于java - 如何对单个事务多次调用@Transactional方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58317714/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com