spring - 在运行三足事务时避免死锁
问题描述
在会计系统中,资金可以在账户之间转移。
为了避免重复预订交易(账户之间的转账)时出现死锁,账户之间的转账是基于id order:
@Transactional
override fun doubleBookPrepaid(eventId: Long, srcPurposefulAccountId: PurposefulAccountId, trgPurposefulAccountId: PurposefulAccountId, amount: Money): Pair<Money, Money>? =
if (srcPurposefulAccountId.accountId < trgPurposefulAccountId.accountId) { // Locking minimal account ID first, to prevent deadlocks.
val srcBooking = bookPrepaid(eventId, srcPurposefulAccountId, -amount)
val trgBooking = bookPrepaid(eventId, trgPurposefulAccountId, amount)
T(srcBooking, trgBooking)
}
else {
val trgBooking = bookPrepaid(eventId, trgPurposefulAccountId, amount)
val srcBooking = bookPrepaid(eventId, srcPurposefulAccountId, -amount)
T(srcBooking, trgBooking)
}
我怎样才能为三边交易完成相同的结果?在这种交易中,一个账户会在同一笔交易中向两个账户转账:
data class PurposefulAccountTransfer(val trgPurposefulAccountId: PurposefulAccountId, val amount: Money)
@Transactional
fun threeLegBookPrepaid(eventId: Long, srcPurposefulAccountId: PurposefulAccountId, purposefulAccountTransfer: PurposefulAccountTransfer, secondPurposefulAccountTransfer: PurposefulAccountTransfer) {
val srcBooking = bookPrepaid(eventId, srcPurposefulAccountId, -(purposefulAccountTransfer.amount + secondPurposefulAccountTransfer.amount))
val trgFirstBooking = bookPrepaid(eventId, purposefulAccountTransfer.trgPurposefulAccountId, purposefulAccountTransfer.amount)
val trgSecondBooking = bookPrepaid(eventId, secondPurposefulAccountTransfer.trgPurposefulAccountId, secondPurposefulAccountTransfer.amount)
}
解决方案
您只需要对所有命令进行排序以确保没有循环依赖项(假设T()
接受vararg
):
fun threeLegBookPrepaid(eventId: Long, ...) {
val txs = sortedMapOf(
srcAccountId to bookPrepaid(eventId, srcAccountId , ...),
trg1AccountId to bookPrepaid(eventId, trg1AccountId, ...),
trg2AccountId to bookPrepaid(eventId, trg2AccountId, ...)
)
.map { it.component2() }
.toTypedArray()
T(*txs)
}
这可以很容易地推广到任意数量的帐户。
推荐阅读
- xamarin.forms - 是否可以为 mapbox 中的一条折线设置更多 Line Dasharray
- android - 空值检查运算符用于颤振的空值
- python - psutil.Process 和 lsof 命令差异
- java - 使用 JOOQ 的查询构建器中的函数 json 对象、json 数组
- terraform-provider-aws - 使用动态块作为安全组入口规则的 Terraform 问题
- wordpress - Elementor - 在标签之后添加自定义代码
- rust - Rust:为什么将未使用的 (_) 参数传递给函数会改变结果
- reactjs - 当页面刷新和状态改变时调用两个组件 React
- typo3 - 如何向通量字段添加上下文帮助或帮助图标?
- javascript - 如何在路线更改后滚动到页面顶部,但返回时保留滚动位置?