簡體   English   中英

可以設置為使Java過期的全局分布式鎖

[英]global distributed lock that can be set to expire Java

我有一個用例,我希望有一個全局分布的鎖。 我們開始使用SELECT .. FOR UPDATE ,但隨着我們擴大服務器數量,這很快就出現了問題。 此外,它沒有考慮檢查鎖定然后死亡並且無法返回鎖定的進程。

我們需要能夠設置鎖定的到期時間(即,如果簽出鎖定的進程在2小時內沒有返回,則鎖定會自動返回到池中)。 我意識到這引入了我們忽略鎖定的問題,但我們相當確定如果在2小時內沒有完成,該過程已經死亡。 這項工作也是冪等的,所以如果不止一次這樣做,那就沒什么大不了的了。

我已經通過了一些分布式鎖定系統的看了看,遇到這種問題,已經非常有幫助。 所有解決方案都延伸到Java的java.util.concurrency.locks.Lock ,這實際上可能是我遇到的問題,因為該接口沒有我需要的過期功能。 我們有一個類似於mongo-java-distributed-lock的策略 ,我們使用MongoDB的findAndModify 我們正在考慮:

作為我們的分布式鎖定機制(都碰巧實現了java.util.concurrency.locks.Lock )。

最大的問題是因為java.util.concurrency.locks.Lock沒有使鎖定過期的選項,所以這些不適合所有目標。 這個答案可能與hazelcast最接近,但它依賴於整個服務器失敗,而不僅僅是一個線程花費太長時間。 另一種選擇是可能使用Samaphore與hazelcast描述這里 我可以有一個收割者線程,如果他們花了太長時間就可以取消其他人的鎖定。 使用Mongo和Redis,我可以利用它們使對象到期的能力,但這似乎不是任何一個庫的一部分,因為它們最終只實現了java.util.concurrency.locks.Lock

所以這只是一個冗長的問題,是否有一個分布式鎖定機制,我可以在N秒后自動過期? 在這種情況下,我應該看一下與java.util.concurrency.locks.Lock不同的機制嗎?

您可以使用Redisson基於Redis服務器。 它實現了熟悉的Java數據結構,包括具有分布式和可伸縮功能的java.util.Lock 包括設置鎖定釋放超時的能力。 用法示例:

Config config = new Config();
// for single server
config.useSingleServer()
      .setAddress("127.0.0.1:6379");
// or 
// for master/slave servers
config.useSentinelConnection()
      .setMasterName("mymaster")
      .addSentinelAddress("127.0.0.1:26389", "127.0.0.1:26379");

Redisson redisson = Redisson.create(config);

Lock lock = redisson.getLock("anyLock");
try {
   // unlock automatically after 10 seconds of hold
   lock.lock(10, TimeUnit.SECONDS);

} finally {
   lock.unlock();
}

...

redisson.shutdown();

你應該考慮使用zookeeper 並且有一個易於使用的庫用於這種“分布式”的東西,它建立在zookeeper: curator框架之上。 我認為你要找的是共享的重入鎖 您還可以檢查食譜中的其他鎖。

這個如何? http://www.gemstone.com/docs/5.5.0/product/docs/japi/com/gemstone/gemfire/distributed/DistributedLockService.html

它的lock方法似乎有你需要的東西:

public abstract boolean lock(Object name, long waitTimeMillis, long leaseTimeMillis)

嘗試獲取名為name的鎖。 獲取鎖定后立即返回true。 如果鎖當前由分布式系統中的此進程或任何其他進程中的另一個線程持有,或者系統中的另一個線程已鎖定整個服務,則此方法在放棄並返回false之前一直嘗試獲取最多等待waitMillis的鎖。 如果獲取了鎖,則會一直保持鎖定,直到調用unlock(對象名稱),或者直到從授予鎖定起已經過了leaseTimeMillis毫秒 - 以先到者為准。

實際上,據我所知, mongo-java-distributed-lock能夠通過使用DistributedLockOptions.setInactiveLockTimeout()來鎖定鎖定。

我還沒有嘗試過,但我想我會......

編輯:我現在也嘗試過,它運作良好......

String lockName = "com.yourcompany.yourapplication.somelock";
int lockTimeoutMilliSeconds = 500;

String dbURI = CWConfig.get().getMongoDBConfig().getDbURI();
DistributedLockSvcFactory lockSvcFactory = new DistributedLockSvcFactory(new DistributedLockSvcOptions(dbURI));
DistributedLockSvc lockSvc = lockSvcFactory.getLockSvc();

DistributedLock lock = lockSvc.create(lockName);
lock.getOptions().setInactiveLockTimeout(lockTimeoutMilliSeconds);
try {
    lock.lock();
    // Do work
} finally {
    lock.unlock();
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM