使用redis 實現分布式鎖

2021-08-14 15:32:49 字數 2856 閱讀 1785

在有些需要高可用的場景中,保證併發量的情況下需要使用分布式鎖來做控制,保證應用的可靠性。我們知道jdk提供了一些常用的鎖比如reentrantlock,reentrantreadwritelock,synchronized。對於這些鎖的實現這裡就不詳細介紹了,在使用過程中這些鎖鎖的是物件,在單伺服器的時候有用。但是現在基本都不是單一伺服器了,一般都會有多台伺服器。對於一些要求高的業務,而且耗時長的任務,比如當客戶端乙個請求到a伺服器時,a伺服器還沒處理完,此時客戶端又請求b伺服器,對於一些非冪等操作,是不允許這樣操作的,比如請求第三方下單的時候,就必須保證只有第一次請求有結果後,才能進行第二次請求,否則可能存在重複下單的過程。這個時候就可以對整個下單過程加鎖,使用分布式鎖。

redis可以實現分布式鎖主要是redis為單程序單執行緒模式,採用佇列模式將併發訪問變成序列訪問,且多客戶端對redis的連線並不存在競爭關係。

使用redis實現分布式鎖主要使用的幾個命令:

setnx

當且僅當 key 不存在,將 key 的值設為 value ,並返回1;若給定的 key 已經存在,則 setnx 不做任何動作,並返回0。

getset命令

將給定 key 的值設為 value ,並返回 key 的舊值 (old value),當 key 存在但不是字串型別時,返回乙個錯誤,當key不存在時,返回nil。

get命令

返回 key 所關聯的字串值,如果 key 不存在那麼返回特殊值 nil 。

del命令

刪除給定的乙個或多個 key ,不存在的 key 會被忽略。

其中setnx和getset可以理解為原子操作,是同步的。

package com.xfl.boot.common.utils.concurrent;

import org.slf4j.logger;

import org.slf4j.logge***ctory;

import org.springframework.dao.dataacces***ception;

import org.springframework.data.redis.connection.redisconnection;

import org.springframework.data.redis.core.rediscallback;

import org.springframework.data.redis.core.stringredistemplate;

import org.springframework.data.redis.serializer.stringredisserializer;

/** * 分布式鎖

*/public

class

redislock

public

redislock(stringredistemplate redistemplate, string lockkey, int timeoutmsecs)

public

redislock(stringredistemplate redistemplate, string lockkey, int timeoutmsecs, int expiremsecs)

public string getlockkey()

public string get(final string key)

return serializer.deserialize(data);

}});

} catch (exception e) ", key);

}return obj != null ? obj.tostring() : null;

}public

boolean

setnx(final string key, final string value)

});} catch (exception e) ", key);

}return obj != null ? (boolean) obj : false;

}private string getset(final string key, final string value)

});} catch (exception e) ", key);

}return obj != null ? (string) obj : null;

}public

synchronized

boolean

lock() throws interruptedexception

string currentvaluestr = this.get(lockkey); // redis裡的時間

if (currentvaluestr != null && long.parselong(currentvaluestr) < system.currenttimemillis())

}timeout -= default_acquiry_resolution_millis;

// 延遲100 毫秒

thread.sleep(default_acquiry_resolution_millis);

}return

false;

}public

synchronized

void

unlock()

}}

string key = "122456";

redislock lock = new redislock(stringredistemplate, key.tostring(),

1000, 2000);

try else

} catch (interruptedexception e) finally

參考資料:

分布式鎖 使用Redis實現分布式鎖

關於分布式鎖的實現,我的前一篇文章講解了如何使用zookeeper實現分布式鎖。關於分布式鎖的背景此處不再做贅述,我們直接討論下如何使用redis實現分布式鎖。關於redis,筆主不打算做長篇大論的介紹,只介紹下redis優秀的特性。支援豐富的資料型別,如string list map set zs...

使用Redis實現分布式鎖

網上大部分建議都是使用setnx,這個本身沒有什麼問題,因為低版本的redis中,只有這個命令可以互斥的set乙個key。但是隨著redis版本的公升高,提供了更多的命令來更好的滿足我們的需求。set keyvalue ex seconds px milliseconds nx xx 這可和你所知道...

使用redis實現分布式鎖

一.redis命令講解 setnx 命令 setnx的含義就是set if not exists,其主要有兩個引數 setnx key,value 該方法是原子的,如果key不存在,則設定當前key成功,返回1 如果當前key已經存在,則設定當前key失敗,返回0。get 命令 get key 獲取...