分散ロックRedis実装
3671 ワード
前編では,分散ロックのデータベース実装について述べたが,分散ロックのredis実装について引き続き述べる.では、redisによって分散ロックを実現するにはどうすればいいのでしょうか.一般的に最も考えやすいコマンドはsetNxですが、redis setNxコマンドを使用する場合、どのような点に注目する必要がありますか? redis分散ロック共通コマンド、SETNX(key,val)キーが存在しない場合のみ、設定に成功し、「1」を返し、否定者は何もせず、「0」を返します.このコマンドの特性を利用してロック操作を行うことができます.同時に2つのスレッドがリソースを競合する場合、そのうちの1つのスレッドが先にリソースを取得し、setnxコマンドを呼び出すと、設定に成功し、「1」に戻り、ロックに成功したことを示します.別のスレッドもsetnxコマンドを呼び出し、keyが設定されていることを示し、ロックに失敗し、再待機する必要があることを示す「0」を返します. expire key timeoutロック中に異常が発生することを防止するために、ロックはずっと解放されず、ロックをかけるkeyにタイムアウト時間、タイムアウト時間の設定を設定する必要があります.すべての分散ロックの実現に考慮する必要があります. delete keyあるkeyを削除し、対応するロックを解放します.
次に、簡単なソース実装を示します.
次に、簡単なソース実装を示します.
/**
*
*/
public class DistributedLock {
private final JedisPool jedisPool;
public DistributedLock(JedisPool jedisPool) {
this.jedisPool = jedisPool;
}
/**
*
* @param lockName key
* @param acquireTimeout
* @param timeout
* @return
*/
public String lockWithTimeout(String lockName, long acquireTimeout, long timeout) {
Jedis conn = null;
String retIdentifier = null;
try {
//
conn = jedisPool.getResource();
// value
String identifier = UUID.randomUUID().toString();
// , key
String lockKey = "lock:" + lockName;
// ,
int lockExpire = (int) (timeout / 1000);
// ,
long end = System.currentTimeMillis() + acquireTimeout;
while (System.currentTimeMillis() < end) {
if (conn.setnx(lockKey, identifier) == 1) {
conn.expire(lockKey, lockExpire);
// value ,
retIdentifier = identifier;
return retIdentifier;
}
// -1 key , key
if (conn.ttl(lockKey) == -1) {
conn.expire(lockKey, lockExpire);
}
try {
Thread.sleep(10);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
} catch (JedisException e) {
e.printStackTrace();
} finally {
if (conn != null) {
conn.close();
}
}
return retIdentifier;
}
/**
*
* @param lockName key
* @param identifier
* @return
*/
public boolean releaseLock(String lockName, String identifier) {
Jedis conn = null;
String lockKey = "lock:" + lockName;
boolean retFlag = false;
try {
conn = jedisPool.getResource();
while (true) {
// lock,
conn.watch(lockKey);
// value , , ,
if (identifier.equals(conn.get(lockKey))) {
Transaction transaction = conn.multi();
transaction.del(lockKey);
List