用redis實現分佈式鎖

通常部署的服務都是在多臺服務器上,不會只有一臺。那麼在分佈式環境下,就會遇到共享資源的問題。比如一個人只能有一條記錄,下次進來就只能修改,而不是再新增。
如果只有一臺服務器,可以使用多線程下的單例模式來控制,但是分佈式下,就不管用了。

有三種方式,一是使用數據庫的樂觀鎖,二是redis的鎖,三是zookeeper提供的鎖。此處介紹reids的,參考這個網址:https://www.cnblogs.com/linjiqin/p/8003838.html

以下爲參考他人博客整理後的代碼。

以下爲調用代碼

String lockKey=“xxxxkey”;
String requestId=UUID.randomUUID().toString();
String lockResult=RedisUtil.lockWithSecond(lockKey,requestId,30);
if(!RedisConstants.LOCK_SUCCESS.equals(lockResult)){
    獲得鎖失敗處理邏輯,可以是暫停等待之類的操作。。。
}

try{
。。。。獲得鎖成功業務邏輯
}catch(Exceptionee){
}finally{
  解鎖
RedisUtil.unLock(lockKey,requestId);
}

redis工具類的加鎖代碼

/**
 *  鎖的超時單位爲秒
 *  @param lockKey,鎖的key(名稱)
 * @param requestId,加鎖的客戶端id
 * @param expireTime 失效時間
 *  返回 OK 表示成功
 */
public static String lockWithSecond(String lockKey,String requestId,int expireTime){
   String result=myRedisClusterForHessian.getJedisCluster().set(
            lockKey,
            requestId,
            "NX",
            "EX",
           expireTime);
   return result;
}

redis工具類的解鎖代碼

/**
 * 解鎖,0-失敗,1-成功
 * @return
 */
public static Long unLock(String lockKey,String requestId){
    if (requestId.equals(myRedisClusterForHessian.getJedisCluster().get(lockKey))) {
        return myRedisClusterForHessian.getJedisCluster().del(lockKey);
    }else{
        return 0L;
    }
}

其實就是用了jedis提供的方法,myRedisClusterForHessian只不過是封裝了集羣下獲取jedis的的方法。
核心方法如下:
jedis.set(lockKey, requestId, SET_IF_NOT_EXIST, SET_WITH_EXPIRE_TIME, expireTime);
調用的底層實現

/**
 * Set the string value as value of the key. The string can't be longer than 1073741824 bytes (1
 * GB).
 * @param key
 * @param value
 * @param nxxx NX|XX, NX -- Only set the key if it does not already exist. XX -- Only set the key
 *          if it already exist.
 * @param expx EX|PX, expire time units: EX = seconds; PX = milliseconds
 * @param time expire time in the units of <code>expx</code>
 * @return Status code reply
 */
public String set(final String key, final String value, final String nxxx, final String expx,
    final long time) {
  checkIsInMultiOrPipeline();
  client.set(key, value, nxxx, expx, time);
  return client.getStatusCodeReply();
}

解釋如下:
Key,鎖的key(名稱)
requestId,加鎖的客戶端id
nxxx NX|XX, NX – 如果不存在設置key,存在則不做; XX – 如果key存在才設置,不存在不做
expx EX|PX, EX—失效時間單位爲秒,PX—失效時間單位爲毫秒
time 失效時間長度
返回 OK 表示成功

就是通過uuid來給同一個key加鎖,不同服務器,uuid不同,誰鎖的,只能誰解鎖。或者到達超時時間後自動解鎖。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章