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 可以配置自定义的 insertupdaterenew 查询。为此,公开了相应的 setter 和 getter。例如,PostgreSQL 提示的插入查询可以这样配置

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

从版本 6.4 开始,LockRepository.delete() 方法返回移除分布式锁所有权的结果。如果锁的所有权已过期,则 JdbcLockRegistry.JdbcLock.unlock() 方法会抛出 ConcurrentModificationException

从版本 7.0 开始,JdbcLock 实现了 DistributedLock 接口,以支持锁状态数据的自定义存活时间 (TTL) 功能。现在可以使用 lock(Duration ttl)tryLock(long time, TimeUnit unit, Duration ttl) 方法获取 JdbcLock,并指定一个存活时间 (TTL) 值。JdbcLockRegistry 现在提供了新的 renewLock(Object lockKey, Duration ttl) 方法,允许您使用自定义存活时间值续订锁。存储在同一 JdbcLockRegistry 中的所有 JdbcLock 实例的默认存活时间现在可以通过新的构造函数 JdbcLockRegistry(LockRepository client, Duration expireAfter) 设置。LockRepositoryDefaultLockRepository 的 API 也已修改以支持此功能。

如果您已经在使用早期版本的 JdbcLockRegistryDefaultLockRepository,请在升级到此版本之前执行必要的 DDL 以修改 INT_LOCK 表。

以下是 Postgres DDL 的示例,用于向锁表添加新列

ALTER TABLE INT_LOCK ADD EXPIRED_AFTER TIMESTAMP NOT NULL;
© . This site is unofficial and not affiliated with VMware.