JDBC Lock Registry

版本 4.3 引入了 JdbcLockRegistry。某些组件(例如,聚合器和重新排序器)使用从 LockRegistry 实例获取的锁来确保一次只有一个线程操作一个组。DefaultLockRegistry 在单个组件中执行此功能。你现在可以在这些组件上配置外部锁注册表。与共享 MessageGroupStore 一起使用时,你可以使用 JdbcLockRegistry 为多个应用程序实例提供此功能,使得同一时间只有一个实例可以操作该组。

Version 4.3 introduced the JdbcLockRegistry. Certain components (for example, aggregator and resequencer) use a lock obtained from a LockRegistry instance to ensure that only one thread manipulates a group at a time. The DefaultLockRegistry performs this function within a single component. You can now configure an external lock registry on these components. When used with a shared MessageGroupStore, you can use the JdbcLockRegistry to provide this functionality across multiple application instances, such that only one instance can manipulate the group at a time.

当本地线程释放锁后,另一个本地线程通常可以在立即获取锁。如果线程使用其他注册表实例释放锁,则获取锁可能需要长达 100 毫秒。

When a lock is released by a local thread, another local thread can generally acquire the lock immediately. If a lock is released by a thread that uses a different registry instance, it can take up to 100ms to acquire the lock.

JdbcLockRegistry 基于 LockRepository 抽象,其有一个 DefaultLockRepository 实现。数据库模式脚本位于 org.springframework.integration.jdbc 包中,该包针对特定 RDBMS 供应商进行了划分。例如,以下清单显示了 H2 锁表的 DDL:

The JdbcLockRegistry is based on the LockRepository abstraction, which has a DefaultLockRepository implementation. The database schema scripts are located in the org.springframework.integration.jdbc package, which is divided for the particular RDBMS vendors. For example, the following listing shows the H2 DDL for the lock table:

CREATE TABLE INT_LOCK  (
    LOCK_KEY CHAR(36),
    REGION VARCHAR(100),
    CLIENT_ID CHAR(36),
    CREATED_DATE TIMESTAMP NOT NULL,
    constraint INT_LOCK_PK primary key (LOCK_KEY, REGION)
);

可以根据目标数据库设计要求更改 INT_。因此,你必须在 DefaultLockRepository bean 定义中使用 prefix 属性。

The INT_ can be changed according to the target database design requirements. Therefore, you must use prefix property on the DefaultLockRepository bean definition.

有时,一个应用程序已进入这样的状态,即它不能释放分布式锁并移除数据库中的特定记录。为此目的,此类死锁可在下一次锁定调用中由其他应用程序到期。DefaultLockRepository 中的 timeToLive (TTL) 选项为此目的提供。你可能还希望为给定的 DefaultLockRepository 实例存储的锁指定 CLIENT_ID。如果要指定 ID 以与 DefaultLockRepository 关联,可将其指定为构造函数参数。

Sometimes, one application has moved to such a state that it cannot release the distributed lock and remove the particular record in the database. For this purpose, such deadlocks can be expired by the other application on the next locking invocation. The timeToLive (TTL) option on the DefaultLockRepository is provided for this purpose. You may also want to specify CLIENT_ID for the locks stored for a given DefaultLockRepository instance. If so, you can specify the id to be associated with the DefaultLockRepository as a constructor parameter.

从 5.1.8 版开始,JdbcLockRegistry 可配置 idleBetweenTries - 在锁记录插入/更新执行之间休眠的 Duration。默认情况下,它是 100 毫秒,并且在某些环境中,非领导者会频繁使用数据源污染连接。

Starting with version 5.1.8, the JdbcLockRegistry can be configured with the idleBetweenTries - a Duration to sleep between lock record insert/update executions. By default, it is 100 milliseconds and in some environments non-leaders pollute connections with data source too often.

从5.4版本开始,引入了`RenewableLockRegistry`接口并将其添加到`JdbcLockRegistry`中。在锁定过程可能比锁定生命周期的生存时间更长的情况下,必须在锁定过程中调用`renewLock()`方法。因此,生存时间可以大大减少,并且部署可以快速地重新获得丢失的锁。

Starting with version 5.4, the RenewableLockRegistry interface has been introduced and added to JdbcLockRegistry. The renewLock() method must be called during locked process in case of the locked process would be longer than time to live of the lock. So the time to live can be highly reduce and deployments can retake a lost lock quickly.

锁定续订只能在当前线程持有锁时执行。

The lock renewal can be done only if the lock is held by the current thread.

从5.5.6版开始,`JdbcLockRegistry`通过`JdbcLockRegistry.setCacheCapacity()`自动清理`JdbcLockRegistry.locks`中的JdbcLock的缓存。有关更多信息,请参阅其JavaDoc文档。

Starting with version 5.5.6, the JdbcLockRegistry is support automatically clean up cache for JdbcLock in JdbcLockRegistry.locks via JdbcLockRegistry.setCacheCapacity(). See its JavaDocs for more information.

从 6.0 版本开始,可以向 DefaultLockRepository 提供 PlatformTransactionManager,而不是依赖于应用程序上下文中主要的 bean。

Starting with version 6.0, the DefaultLockRepository can be supplied with a PlatformTransactionManager instead of relying on the primary bean from the application context.

从 6.1 版本开始,DefaultLockRepository 可针对自定义的 insertupdaterenew 查询进行配置。为此目的,公开各自的 setter 和 getter 方法。例如,可以这样配置 PostgreSQL 提示的插入查询:

Starting with version 6.1, the DefaultLockRepository can be configured for custom insert, update and renew queries. For this purpose the respective setters and getters are exposed. For example, an insert query for PostgreSQL hint can be configured like this:

lockRepository.setInsertQuery(lockRepository.getInsertQuery() + " ON CONFLICT DO NOTHING");