Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/sharepoint/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Spring集成JDBC锁故障_Jdbc_Locking_Spring Integration - Fatal编程技术网

Spring集成JDBC锁故障

Spring集成JDBC锁故障,jdbc,locking,spring-integration,Jdbc,Locking,Spring Integration,我不理解从JdbcLockRegistry获得的分布式锁的行为 @Bean public LockRepository lockRepository(DataSource datasource) { return new DefaultLockRepository(datasource); } @Bean public LockRegistry lockRegistry(LockRepository repository) { return new JdbcLockRegist

我不理解从JdbcLockRegistry获得的分布式锁的行为

@Bean
public LockRepository lockRepository(DataSource datasource) {
    return new DefaultLockRepository(datasource);
}

@Bean
public LockRegistry lockRegistry(LockRepository repository) {
    return new JdbcLockRegistry(repository);
}
我的项目运行在PostgreSQL上,Spring启动版本是2.2.2 这是演示用例:

@GetMapping("/isolate")
public String isolate() throws InterruptedException {
    Lock lock = registry.obtain("the-lock");
    if (lock.tryLock(10, TimeUnit.SECONDS)) {   // close
        try {
            Thread.sleep(30 * 1000L);
        } finally {
            lock.unlock();                      // open
        }
    } else {
        return "rejected";
    }
    return "acquired";
}
注意:当使用Hazelcast分布式锁时,该用例有效

观察到的行为是通过对第一个实例的API调用在数据库中正式注册第一个锁。 然后,在30秒内,在另一个实例(其他端口)上请求第二次打开,它将更新现有的int_锁表的行(client_id更改),而不是失败。因此,第一个端点在30秒后交付(无解锁失败),第二个端点在其自身的30秒后交付。没有相互排斥

以下是单个采集的日志:

Trying to acquire lock...
Executing prepared SQL update
Executing prepared SQL statement [DELETE FROM INT_LOCK WHERE REGION=? AND LOCK_KEY=? AND CREATED_DATE<?]
Executing prepared SQL update
Executing prepared SQL statement [UPDATE INT_LOCK SET CREATED_DATE=? WHERE REGION=? AND LOCK_KEY=? AND CLIENT_ID=?]
Executing prepared SQL update
Executing prepared SQL statement [INSERT INTO INT_LOCK (REGION, LOCK_KEY, CLIENT_ID, CREATED_DATE) VALUES (?, ?, ?, ?)]
Processing...
Executing prepared SQL update
Executing prepared SQL statement [DELETE FROM INT_LOCK WHERE REGION=? AND LOCK_KEY=? AND CLIENT_ID=?]
正在尝试获取锁。。。
执行准备好的SQL更新

执行准备好的SQL语句[DELETE FROM INT_LOCK WHERE REGION=?AND LOCK_KEY=?并创建了_DATE。碰巧存储库的TTL默认为10秒,就像我在特定用例中的超时一样。因此,锁显然在超时时间之前死亡(删除)。 下面是一个解决方案:

@Bean
public LockRepository lockRepository(DataSource datasource) {
    DefaultLockRepository repository = new DefaultLockRepository(datasource);
    repository.setTimeToLive(60 * 1000);
    return repository;
}

为了维护一个锁,我尝试利用DefaultLockRepository#acquire(由lock#lock调用),它在插入新锁之前(以及在清除过期锁之后,如前所述)尝试更新:

@GetMapping(“/isolate”)
公共字符串隔离()引发InterruptedException{
Lock=registry.get(“锁”);
log.warn(“试图获取锁…”);
if(lock.tryLock(10,TimeUnit.SECONDS)){//关闭锁
试一试{
对于(inti=0;i<6;i++){//非常。。。
log.warn(“正在处理…”);
线程。睡眠(5*1000L);/…长任务
lock.lock();//调试保持(锁更新)
}
}最后{
如果(!repository.isAcquired(“锁”)){
抛出新的非法状态异常(“锁丢失”);
}否则{
lock.unlock();//打开锁
}
}
}否则{
返回“拒绝”;
}
返回“已获得”;
}
但这并没有像预期的那样起作用(注意:在本测试中,ttl默认为10秒);
尽管我可以在PostgreSQL的控制台中看到锁定日期的变化,但最终我总是会收到一个lock lost IllegalStateException异常。

是的!这正是答案。在Hazelcast
leaseTimeout
的情况下,默认情况下太长了-
long。最大值
。根据记录,我尝试在使用reposit解锁之前检测租约丢失ory.isAcquired(“锁”),但由于此函数在操作前清理超时锁(!!)这没有帮助,这是对的,因为
TTL
比所有其他功能都有更高的优先级。@ArtemBilan明白。那么,我如何检测自己的锁丢失呢?是否有一个过程可以确保我将锁保持在很长的过程中,可能是通过定期重新获取它?Thx提前我只会使TTL太长。锁是g即使是应用程序停止,仍然需要解锁。
@GetMapping("/isolate")
public String isolate() throws InterruptedException {
    Lock lock = registry.obtain("the-lock");
    log.warn("Trying to acquire lock...");
    if (lock.tryLock(10, TimeUnit.SECONDS)) {    // close lock
        try {
            for (int i=0; i < 6; i++) {          // very...
                log.warn("Processing...");
                Thread.sleep(5 * 1000L);         // ... long task
                lock.lock();                     //DEBUG holding (lock update)
            }
        } finally {
            if (!repository.isAcquired("the-lock")) {
                throw new IllegalStateException("lock lost");
            } else {
                lock.unlock();                   // open lock
            }
        }
    } else {
        return "rejected";
    }
    return "acquired";
}