最近專案中,基本功能實現了,準備都訪問多的介面加快取。當然快取就想到了redis。正好自己也查了查redis帶來的一些問題:快取穿透、快取併發、熱點快取等。
也想到自己負責的模組涉及到資金,同一時間只能有乙個人操作,想象一下,同一時間2個使用者同時還款放款,一個人賬戶增加乙個減少,為了方式同時運算元據不一致,需要鎖。如果是單體服務,可以直接利用資料庫的行鎖或者表鎖。如果是微服務集群,多個客戶端同時修改乙個共享資料就需要分布式鎖了。
場景:秒殺
現在有100個商品,進行秒殺,因為商品**便宜,所以就會有很多人來搶。首先我們要保證的就是:
1 商品最後不能成負數
2 防止超出資料庫連線池數目
3 保證在分布式部署的應用集群中,同乙個方法在同一時間只能被一台機器上的乙個執行緒執行。
業務核心:
每個使用者訪問的時候,先要獲取鎖,如果獲取到了,就可以購買商品,如果獲取不到就再次訪問。
/**
* 分布式鎖嘗試
* 每個使用者訪問的時候,先要獲取鎖,如果獲取到了,就可以購買商品,如果獲取不到就再次訪問**
*@param feecode
*@throws exception
*/public
void
stock(string feecode) throws exception
//1.查詢商品庫存。為0則買完了
if (count<1)else
//解鎖
redisservice.unlock(feecode, string.valueof(time));
}
分布式鎖,加鎖:
這裡要注意的是,使用redis的setnx來實現加鎖。setnx是如果key不存在就儲存到redis中,並返回1,否則如果key存在,就什麼也不做,返回0。
這裡呢,因為很多人搶一種產品,所以key可以為producttypeid ,value為 當前時間+超時時間。
針對這個超時時間呢?大家在平常的時候很常見,就是比如在某寶、某東、12306等買東西的時候,當新增購物車後,前去結賬,結賬的時候,都會有乙個請在30分鐘內付款。否則就自動放棄。我們的這個超時時間就是類似付款時候的30分鐘。這個是要根據我們具體的業務具體設定的。
如果鎖過期,獲取上乙個鎖的時間,如果鎖過期,也就是儲存的鎖的值小於當前時間,那麼使用getset方法把值替換掉。
/**
* 分布式鎖,加鎖
*@param key
*@param value 當前時間+超時時間
*@return
*/public
boolean
lock(string key, string value)
string currentvalue = (string) redistemplate.opsforvalue().get(key);
//如果鎖過期
if (!stringutils.isempty(currentvalue) && long.parselong(currentvalue) < system.currenttimemillis())
}return
false;
}
分布式鎖,解鎖:
我們先來根據
/**
* 分布式鎖,解鎖
*@param key
*@param value
*/public
void
unlock(string key,string value)
}catch (exception e)",e);}}
保證在分布式部署的應用集群中,同乙個方法在同一時間只能被一台機器上的乙個執行緒執行。分布式鎖就可以實現這個功能。用到了redis的兩個命令,setnx和getset。了解一下。 redis分布式鎖
redis分布式鎖 直接上 我寫了四個redis分布式鎖的方法,大家可以提個意見 第一種方法 redis分布式鎖 param timeout public void lock long timeout thread.sleep 100 catch exception e override publi...
Redis分布式鎖
分布式鎖一般有三種實現方式 1.資料庫樂觀鎖 2.基於redis的分布式鎖 3.基於zookeeper的分布式鎖.首先,為了確保分布式鎖可用,我們至少要確保鎖的實現同時滿足以下四個條件 互斥性。在任意時刻,只有乙個客戶端能持有鎖。不會發生死鎖。即使有乙個客戶端在持有鎖的期間崩潰而沒有主動解鎖,也能保...
redis分布式鎖
使用redis的setnx命令實現分布式鎖 redis為單程序單執行緒模式,採用佇列模式將併發訪問變成序列訪問,且多個客戶端對redis的連線並不存在競爭關係。redis的setnx命令可以方便的實現分布式鎖。setnx key value 將key的值設為value,當且僅當key不存在。如給定的...