JDBC Lock Registry
版本 4.3 引入了JdbcLockRegistry
.
某些组件(例如,aggregator 和 resequencer)使用从LockRegistry
实例来确保一次只有一个线程作一个组。
这DefaultLockRegistry
在单个组件中执行此功能。
现在,您可以在这些组件上配置外部锁注册表。
当与共享的MessageGroupStore
中,您可以使用JdbcLockRegistry
跨多个应用程序实例提供此功能,以便一次只有一个实例可以作组。
当本地线程释放锁时,另一个本地线程通常可以立即获取该锁。 如果锁由使用其他注册表实例的线程释放,则获取锁可能需要长达 100 毫秒的时间。
这JdbcLockRegistry
基于LockRepository
abstraction 的 API 中,它有一个DefaultLockRepository
实现。
数据库架构脚本位于org.springframework.integration.jdbc
软件包,该软件包针对特定的 RDBMS 供应商进行划分。
例如,下面的清单显示了 lock table 的 H2 DDL:
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_
可以根据目标数据库设计要求进行更改。
因此,您必须使用prefix
属性DefaultLockRepository
bean 定义。
有时,一个应用程序已移动到无法释放分布式锁并删除数据库中的特定记录的状态。
为此,此类死锁可以在下一次锁定调用时由其他应用程序过期。
这timeToLive
(TTL) 选项DefaultLockRepository
为此目的而提供。
您可能还需要指定CLIENT_ID
对于为给定DefaultLockRepository
实例。
如果是这样,您可以指定id
以与DefaultLockRepository
作为构造函数参数。
从版本 5.1.8 开始,JdbcLockRegistry
可以使用idleBetweenTries
-一个Duration
在锁定记录插入/更新执行之间休眠。
默认情况下,它是100
毫秒,并且在某些环境中,非领导者会过于频繁地污染与数据源的连接。
从版本 5.4 开始,RenewableLockRegistry
interface 已引入并添加到JdbcLockRegistry
.
这renewLock()
方法必须在锁定的进程期间调用,以防锁定的进程比锁定的生存时间长。
因此,生存时间可以大大缩短,部署可以快速重新获得丢失的锁。
仅当锁由当前线程持有时,才能进行锁续订。 |
从版本 5.5.6 开始,JdbcLockRegistry
支持自动清理 JdbcLock 的缓存JdbcLockRegistry.locks
通过JdbcLockRegistry.setCacheCapacity()
.
有关更多信息,请参阅其 JavaDocs。
从版本 6.0 开始,DefaultLockRepository
可随附PlatformTransactionManager
而不是依赖于应用程序上下文中的主 bean。
从版本 6.1 开始,DefaultLockRepository
可以配置为自定义insert
,update
和renew
查询。
为此,公开了相应的 setter 和 getter。
例如,PostgreSQL 提示的插入查询可以按如下方式配置:
lockRepository.setInsertQuery(lockRepository.getInsertQuery() + " ON CONFLICT DO NOTHING");
从版本 6.4 开始,LockRepository.delete()
方法返回删除分布式锁的所有权的结果。
而JdbcLockRegistry.JdbcLock.unlock()
方法 throwConcurrentModificationException
如果锁的所有权已过期。