javaredis鎖
A. java鏈接redis 是什麼協議
要在Java程序中使用使用操作Redis,需要確保有Redis的Java驅動程序和Java設置在機器上。可以檢查看Java教程-學習如何在機器上安裝Java。現在,讓我們來看看如何設置Redis的Java驅動程序。
需要下載jedis.jar。請一定要下載它的最新版本。
需要包括jedis.jar到你的類路徑中。
連接到Redis伺服器
import redis.clients.jedis.Jedis;
public class RedisJava {
public static void main(String[] args) {
//Connecting to Redis server on localhost
Jedis jedis = new Jedis("localhost");
System.out.println("Connection to server sucessfully");
//check whether server is running or not
System.out.println("Server is running: "+jedis.ping());
}
}
B. java 鏈接redis 怎麼加鎖
我介紹一下Redis分布式鎖吧:
一、定義redis實現分布式鎖的介面
[java]viewplainprint?
packagecom.iol.common.util.concurrent.locks;
importjava.io.Serializable;
/**
*Description:定義redis實現分布式鎖的演算法<br/>
*_SMALL_TAIL.<br/>
*ProgramName:IOL_SMALL_TAIL<br/>
*Date:2015年11月8日
*
*@author王鑫
*@version1.0
*/
{
/**
*加鎖演算法<br/>
*@paramkey
*@return
*/
publicbooleanlock(Stringkey);
/**
*解鎖演算法<br/>
*@paramkey
*@return
*/
publicbooleanunLock(Stringkey);
}
二、redis分布式鎖基礎演算法實現
[java]viewplainprint?
packagecom.iol.common.util.concurrent.locks.arithmetic;
importorg.slf4j.Logger;
importorg.slf4j.LoggerFactory;
importcom.iol.common.util.concurrent.locks.IRedisComponent;
importcom.iol.common.util.concurrent.locks.IRedisLockArithmetic;
/**
*Description:redis分布式鎖基礎演算法實現<br/>
*_SMALL_TAIL.<br/>
*ProgramName:IOL_SMALL_TAIL<br/>
*Date:2015年11月9日
*
*@author王鑫
*@version1.0
*/
{
/**
*serialVersionUID
*/
=-8333946071502606883L;
privateLoggerlogger=LoggerFactory.getLogger(RedisLockBaseArithmetic.class);
/**
*redis操作方法
*/
;
/**
*超時時間,以毫秒為單位<br/>
*默認為5分鍾
*/
privatelongovertime=5*60*1000L;
/**
*休眠時長,以毫秒為單位<br/>
*默認為100毫秒
*/
privatelongsleeptime=100L;
/**
*當前時間
*/
privatelongcurrentLockTime;
/**
*@
*/
publicvoidsetRedisComp(IRedisComponentredisComp){
this.redisComp=redisComp;
}
/**
*@paramovertimetheovertimetoset
*/
publicvoidsetOvertime(longovertime){
this.overtime=overtime;
}
/**
*@
*/
publicvoidsetSleeptime(longsleeptime){
this.sleeptime=sleeptime;
}
/*(non-Javadoc)
*@seecom.iol.common.util.concurrent.locks.IRedisLockArithmetic#lock(java.lang.String,java.lang.Long)
*/
@Override
publicbooleanlock(Stringkey){
while(true){
//當前加鎖時間
currentLockTime=System.currentTimeMillis();
if(redisComp.setIfAbsent(key,currentLockTime)){
//獲取鎖成功
logger.debug("直接獲取鎖{key:{},currentLockTime:{}}",key,currentLockTime);
returntrue;
}else{
//其他線程佔用了鎖
logger.debug("檢測到鎖被佔用{key:{},currentLockTime:{}}",key,currentLockTime);
LongotherLockTime=redisComp.get(key);
if(otherLockTime==null){
//其他系統釋放了鎖
//立刻重新嘗試加鎖
logger.debug("檢測到鎖被釋放{key:{},currentLockTime:{}}",key,currentLockTime);
continue;
}else{
if(currentLockTime-otherLockTime>=overtime){
//鎖超時
//嘗試更新鎖
logger.debug("檢測到鎖超時{key:{},currentLockTime:{},otherLockTime:{}}",key,currentLockTime,otherLockTime);
LongotherLockTime2=redisComp.getAndSet(key,currentLockTime);
if(otherLockTime2==null||otherLockTime.equals(otherLockTime2)){
logger.debug("獲取到超時鎖{key:{},currentLockTime:{},otherLockTime:{},otherLockTime2:{}}",key,currentLockTime,otherLockTime,otherLockTime2);
returntrue;
}else{
sleep();
//重新嘗試加鎖
logger.debug("重新嘗試加鎖{key:{},currentLockTime:{}}",key,currentLockTime);
continue;
}
}else{
//鎖未超時
sleep();
//重新嘗試加鎖
logger.debug("重新嘗試加鎖{key:{},currentLockTime:{}}",key,currentLockTime);
continue;
}
}
}
}
}
/*(non-Javadoc)
*@seecom.iol.common.util.concurrent.locks.IRedisLockArithmetic#unLock(java.lang.String)
*/
@Override
publicbooleanunLock(Stringkey){
logger.debug("解鎖{key:{}}",key);
redisComp.delete(key);
returntrue;
}
/**
*休眠<br/>
*@paramsleeptime
*/
privatevoidsleep(){
try{
Thread.sleep(sleeptime);
}catch(InterruptedExceptione){
thrownewLockException("線程異常中斷",e);
}
}
}
C. linux java連接redis必須用密碼嗎
也不是必須用,得看你自己的配置的,在redis的redis.conf文件中有一個標簽叫requirepass,如果把注釋打開,則需要密碼,如果不打開,則不用密碼,但是一般為了安全,建議你帶上密碼
D. java redis對象鎖怎麼使用
那是共享鎖,不是對象鎖。
E. java怎麼實現redis分布式鎖
Redis有一系列的命令,特點是以NX結尾,NX是Not eXists的縮寫,如SETNX命令就應該理解為:SET if Not eXists。這系列的命令非常有用,這里講使用SETNX來實現分布式鎖。
用SETNX實現分布式鎖
利用SETNX非常簡單地實現分布式鎖。例如:某客戶端要獲得一個名字foo的鎖,客戶端使用下面的命令進行獲取:
SETNX lock.foo <current Unix time + lock timeout + 1>
如返回1,則該客戶端獲得鎖,把lock.foo的鍵值設置為時間值表示該鍵已被鎖定,該客戶端最後可以通過DEL lock.foo來釋放該鎖。
如返回0,表明該鎖已被其他客戶端取得,這時我們可以先返回或進行重試等對方完成或等待鎖超時。
解決死鎖
上面的鎖定邏輯有一個問題:如果一個持有鎖的客戶端失敗或崩潰了不能釋放鎖,該怎麼解決?我們可以通過鎖的鍵對應的時間戳來判斷這種情況是否發生了,如果當前的時間已經大於lock.foo的值,說明該鎖已失效,可以被重新使用。
發生這種情況時,可不能簡單的通過DEL來刪除鎖,然後再SETNX一次,當多個客戶端檢測到鎖超時後都會嘗試去釋放它,這里就可能出現一個競態條件,讓我們模擬一下這個場景:
C0操作超時了,但它還持有著鎖,C1和C2讀取lock.foo檢查時間戳,先後發現超時了。
C1 發送DEL lock.foo
C1 發送SETNX lock.foo 並且成功了。
C2 發送DEL lock.foo
C2 發送SETNX lock.foo 並且成功了。
這樣一來,C1,C2都拿到了鎖!問題大了!
幸好這種問題是可以避免D,讓我們來看看C3這個客戶端是怎樣做的:
C3發送SETNX lock.foo 想要獲得鎖,由於C0還持有鎖,所以Redis返回給C3一個0
C3發送GET lock.foo 以檢查鎖是否超時了,如果沒超時,則等待或重試。
反之,如果已超時,C3通過下面的操作來嘗試獲得鎖:
GETSET lock.foo <current Unix time + lock timeout + 1>
通過GETSET,C3拿到的時間戳如果仍然是超時的,那就說明,C3如願以償拿到鎖了。
如果在C3之前,有個叫C4的客戶端比C3快一步執行了上面的操作,那麼C3拿到的時間戳是個未超時的值,這時,C3沒有如期獲得鎖,需要再次等待或重試。留意一下,盡管C3沒拿到鎖,但它改寫了C4設置的鎖的超時值,不過這一點非常微小的誤差帶來的影響可以忽略不計。
注意:為了讓分布式鎖的演算法更穩鍵些,持有鎖的客戶端在解鎖之前應該再檢查一次自己的鎖是否已經超時,再去做DEL操作,因為可能客戶端因為某個耗時的操作而掛起,操作完的時候鎖因為超時已經被別人獲得,這時就不必解鎖了。
示例偽代碼
根據上面的代碼,我寫了一小段Fake代碼來描述使用分布式鎖的全過程:
# get lock
lock = 0
while lock != 1:
timestamp = current Unix time + lock timeout + 1
lock = SETNX lock.foo timestamp
if lock == 1 or (now() > (GET lock.foo) and now() > (GETSET lock.foo timestamp)):
break;
else:
sleep(10ms)
# do your job
do_job()
# release
if now() < GET lock.foo:
DEL lock.foo
是的,要想這段邏輯可以重用,使用python的你馬上就想到了Decorator,而用Java的你是不是也想到了那誰?AOP + annotation?行,怎樣舒服怎樣用吧,別重復代碼就行。