JVMS上的JDBC LockRegistry

时间:2019-06-14 19:16:06

标签: spring-integration

我的应用程序服务是否使用应该在@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存储中存在到期的锁),直到解锁或到期为止。

我的理解不正确吗?

3 个答案:

答案 0 :(得分:0)

您必须使用其他ID。相同意味着相同的客户端。用于特殊用例。使用不同的ID,因为它们是不同的实例

答案 1 :(得分:0)

这按设计工作。我没有正确配置DefaultLockRepository,默认的ttl比我的服务(人工等待)锁定时间短。我很抱歉。 :)乔什·朗(Josh Long)帮助我弄清楚了:)

答案 2 :(得分:0)

这里的行为很微妙(或者一旦你看到它是如何工作的就很明显),而且文档的普遍缺乏也无济于事,所以这是我的经验。

我通过查看 DefaultLockRepository 中的 SQL 创建了一个锁表,它似乎暗示了 REGIONLOCK_KEYCLIENT_ID 的复合主键 - 这是错误的

我随后在 spring-integration-jdbc JAR 中找到了 SQL 脚本,在那里我可以看到复合主键 MUST BE 仅在 REGIONLOCK_KEY 上作为@ArtemBilan 说。

原因是锁不关心客户端,显然,所以主键必须只是REGIONLOCK_KEY列。这些列在获取锁时使用,如果另一个客户端尝试获取用于限制其他客户端 ID 的锁,则会发生密钥冲突。

这也意味着,正如@ArtemBilan 所说,每个客户端实例都必须有一个唯一的 ID,这是在构建时未指定 ID 时的默认行为。