我的应用程序服务是否使用应该在@Transaction中运行的JDBC LockRepository获得锁?
我们有一个示例应用程序服务,该服务可以更新JDBCRepository,并且由于该应用程序可以在多个JVMS(无头)上运行。我们需要全局锁来序列化这些更新。
我查看了您的测试,希望我的用例也能正常工作。 ... JdbcLockRegistryDifferentClientTests
我的配置具有DefaultLockRepository和JdbcLockRegistry;
我在两个终端上启动了我的应用程序(java -jar boot.jar)以进行仿真。当我获得一个锁并在我的应用程序服务上发出不带@Transaction的tryLock()时,两个锁几乎立即一个接一个地获得(尽管)。我希望其中一个在至少10秒钟内不会收到它(默认有效期)。
Service (Instance -1) {
Obtain("KEY-1")
tryLock()
DoWork()
unlock();
close();
}
Service (Instance -2) {
Obtain("KEY-1")
tryLock() <-- Wait until the lock expires or the unlock happens
DoWork()
unlock();
close();
}
我在这里DefaultLockRepository 也注意到事务范围(如果未继承)仅在JDBC操作周围。
当我将服务更改为
@Transaction
Service (Instance -1) {
Obtain("KEY-1")
tryLock()
DoWork()
unlock();
close();
}
它按预期工作。
我很确定我错过了什么吗?但是我希望我的锁操作能够遵循全局锁(在JDBC存储中存在到期的锁),直到解锁或到期为止。
我的理解不正确吗?
答案 0 :(得分:0)
您必须使用其他ID。相同意味着相同的客户端。用于特殊用例。使用不同的ID,因为它们是不同的实例
答案 1 :(得分:0)
这按设计工作。我没有正确配置DefaultLockRepository,默认的ttl比我的服务(人工等待)锁定时间短。我很抱歉。 :)乔什·朗(Josh Long)帮助我弄清楚了:)
答案 2 :(得分:0)
这里的行为很微妙(或者一旦你看到它是如何工作的就很明显),而且文档的普遍缺乏也无济于事,所以这是我的经验。
我通过查看 DefaultLockRepository
中的 SQL 创建了一个锁表,它似乎暗示了 REGION
、LOCK_KEY
和 CLIENT_ID
的复合主键 - 这是错误的。
我随后在 spring-integration-jdbc
JAR 中找到了 SQL 脚本,在那里我可以看到复合主键 MUST BE 仅在 REGION
和 LOCK_KEY
上作为@ArtemBilan 说。
原因是锁不关心客户端,显然,所以主键必须只是REGION
和LOCK_KEY
列。这些列在获取锁时使用,如果另一个客户端尝试获取用于限制其他客户端 ID 的锁,则会发生密钥冲突。
这也意味着,正如@ArtemBilan 所说,每个客户端实例都必须有一个唯一的 ID,这是在构建时未指定 ID 时的默认行为。