**redis分布式锁**

redis分布式锁

直接上代码,我写了四个redis分布式锁的方法,大家可以提个意见:
第一种方法:
/**
* redis分布式锁
* @param timeout
*/
public void lock(long timeout) {
long nano = System.nanoTime();
timeout *= 1000000;
try {
while ((System.nanoTime() - nano) < timeout) {
if (this.setnx(key, LOCKED) == 1) {
System.out.println(“add lock ” + key);
this.expire(key, EXPIRE);
locked = true;
break;
}
Thread.sleep(100);
}
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
public void lock() {
    lock(TIME_OUT);
}

public void lock(String key) {
    this.key = key;
    lock();
}
@Override
public void unlock() {
    if (locked) {
        System.out.println("release lock");
        this.del(key);
    }
}

public void unlock(String key) {
    this.key = key;
    unlock();
}

第二种方法:
/**
* 添加分布式锁
* @param lock
* @return
*/
public boolean acquireLock(String lock) {
//通过SETNX试图获取一个lock
boolean success = false;
Jedis jedis = null;
long value = System.currentTimeMillis() + EXPIRE + 1;
//System.out.println(value);

    try {
        jedis = getPool();
        long acquired = jedis.setnx(lock, String.valueOf(value));
        //SETNX成功,则成功获取一个锁
        if (acquired == 1) {
            success = true;
            //SETNX失败,说明锁仍然被其他对象保持,检查其是否已经超时
        }else {
            long oldValue = Long.valueOf(jedis.get(lock));
            //超时
            if (oldValue < System.currentTimeMillis()) {
                String getValue = jedis.getSet(lock, String.valueOf(value));
                // 获取锁成功
                if (Long.valueOf(getValue) == oldValue) {
                    success = true;
                    // 已被其他进程捷足先登了
                }else {
                    success = false;
                }
            }
            //未超时,则直接返回失败
            else {
                success = false;
            }
        }
    } catch (Exception e) {
        System.out.println("[acquireLock(key:" + new String(lock) + ")] jedis Exception:" + e.getMessage());
        returnResource(jedis);
    } finally {
        // 返还到连接池
        returnResource(jedis);
    }
    return success;
}


//释放锁
public void releaseLock(String lock) {
    Jedis jedis = null;
    long current = System.currentTimeMillis();
    try {
        jedis = getPool();
        // 避免删除非自己获取得到的锁
        if (current < Long.valueOf(jedis.get(lock))) {
            jedis.del(lock);
        }
    } catch (Exception e) {
        System.out.println("[releaseLock(key:" + new String(lock) + ")] jedis Exception:" + e.getMessage());
        returnResource(jedis);
    } finally {
        // 返还到连接池
        returnResource(jedis);
    }
}

第三种方法:

public boolean acquire(String lockKey){
int timeout = TIMEOUTMSECS;
Jedis jedis = null;
try {
jedis = getPool();
while (timeout >= 0) {
long expires = System.currentTimeMillis() + EXPIREMSECS + 1;
String expiresStr = String.valueOf(expires); //锁到期时间

            if (jedis.setnx(lockKey, expiresStr) == 1) {
                // lock acquired
                locked = true;
                return true;
            }

            String currentValueStr = jedis.get(lockKey); //redis里的时间
            if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) {
                //判断是否为空,不为空的情况下,如果被其他线程设置了值,则第二个条件判断是过不去的
                // lock is expired

                String oldValueStr = jedis.getSet(lockKey, expiresStr);
                //获取上一个锁到期时间,并设置现在的锁到期时间,
                //只有一个线程才能获取上一个线上的设置时间,因为jedis.getSet是同步的
                if (oldValueStr != null && oldValueStr.equals(currentValueStr)) {
                    //如过这个时候,多个线程恰好都到了这里,但是只有一个线程的设置值和当前值相同,他才有权利获取锁
                    // lock acquired
                    locked = true;
                    return true;
                }
            }
            timeout -= 100;
            Thread.sleep(100);
        }
    } catch (NumberFormatException e) {
        e.printStackTrace();
        returnResource(jedis);
    } catch (InterruptedException e) {
        e.printStackTrace();
        returnResource(jedis);
    } finally {
        // 释放redis对象
        returnResource(jedis);
    }
    return false;
}


//释放锁
public void release(String lockKey) {
    Jedis jedis = null;
    try {
        jedis = getPool();
        jedis.del(lockKey);
    } catch (Exception e) {
        System.out.println("[release(key:" + new String(lockKey) + ")] jedis Exception:" + e.getMessage());
        returnResource(jedis);
    } finally {
        // 返还到连接池
        returnResource(jedis);
    }
}

第四种方法:

/**
* 添加锁
* @param key
* @return
*/
public boolean locked(String key) {
Jedis jedis = null;
long timeout = 0L;
long nano = System.nanoTime();
try {
jedis = getPool();
do {
System.out.println(“lock key: ” + key);
Long i = jedis.setnx(key, key);
if (i == 1) {
jedis.expire(key, DEFAULT_SINGLE_EXPIRE_TIME);
//System.out.println(“get lock, key: ” + key + ” , expire in ” + DEFAULT_SINGLE_EXPIRE_TIME + ” seconds.”);
return Boolean.TRUE;
} else { // 存在锁
String desc = jedis.get(key);
//System.out.println(“key: ” + key + ” locked by another business:” + desc);
}
if (timeout == 0) {
break;
}
Thread.sleep(100);
} while ((System.nanoTime() - nano) < TIME_OUT*1000000);
return Boolean.FALSE;
} catch (JedisConnectionException je) {
System.out.println(je.getMessage());
returnResource(jedis);
} catch (Exception e) {
System.out.println(e.getMessage());
returnResource(jedis);
} finally {
returnResource(jedis);
}
return Boolean.FALSE;
}

/**
 * 释放锁
 * @param key
 */
public void unLocked(String key) {
    List keys = new CopyOnWriteArrayList<>();
    keys.add(key);
    unLocked(keys);
}



/**
 * 批量释放锁
 * @param lockeys
 */
public void unLocked(List lockeys) {
    List keys = new CopyOnWriteArrayList();
    keys.addAll(lockeys);
    Jedis jedis = null;
    try {
        jedis = getPool();
        jedis.del(keys.toArray(new String[0]));
        System.out.println("release lock, keys :" + keys);
    } catch (JedisConnectionException je) {
        System.out.println(je.getMessage());
        returnResource(jedis);
    } catch (Exception e) {
        System.out.println(e.getMessage());
        returnResource(jedis);
    } finally {
        returnResource(jedis);
    }
}


/**
 * 批量添加锁
 * @param keys
 * @return
 */
public boolean locked(List keys) {
    Jedis jedis = null;
    long timeout = 0L;
    try {
        List needLocking = new CopyOnWriteArrayList();
        List locked = new CopyOnWriteArrayList();
        jedis = getPool();
        long nano = System.nanoTime();
        do {
            // 构建pipeline,批量提交
            Pipeline pipeline = jedis.pipelined();
            for (String key : keys) {
                needLocking.add(key);
                pipeline.setnx(key, key);
            }
            System.out.println("lock keys: " + needLocking);
            // 提交redis执行计数
            List results = pipeline.syncAndReturnAll();
            for (int i = 0; i < results.size(); ++i) {
                Long result = (Long) results.get(i);
                String key = needLocking.get(i);
                if (result == 1) {    // setnx成功,获得锁
                    jedis.expire(key, DEFAULT_BATCH_EXPIRE_TIME);
                    locked.add(key);
                }
            }
            needLocking.removeAll(locked);    // 已锁定资源去除

            if (CollectionUtils.isEmpty(needLocking)) {
                return true;
            } else {
                // 部分资源未能锁住
                System.out.println("keys: " + needLocking + " locked by another business:");
            }

            if (timeout == 0) {
                break;
            }
            Thread.sleep(500);
        } while ((System.nanoTime() - nano) < TIME_OUT*1000000);

        // 得不到锁,释放锁定的部分对象,并返回失败
        if (!CollectionUtils.isEmpty(locked)) {
            jedis.del(locked.toArray(new String[0]));
        }
        return false;
    } catch (JedisConnectionException je) {
        System.out.println(je.getMessage());
        returnResource(jedis);
    } catch (Exception e) {
        System.out.println(e.getMessage());
        returnResource(jedis);
    } finally {
        returnResource(jedis);
    }
    return true;
} 
 
  

                            
                        
                    
                    
                    

你可能感兴趣的:(redis)