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