真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

【新夢想老師分享】分布式鎖的正確"姿勢"

一、概述

目前創(chuàng)新互聯(lián)公司已為1000多家的企業(yè)提供了網(wǎng)站建設(shè)、域名、雅安服務(wù)器托管、網(wǎng)站運營、企業(yè)網(wǎng)站設(shè)計、靈寶網(wǎng)站維護等服務(wù),公司將堅持客戶導向、應(yīng)用為本的策略,正道將秉承"和諧、參與、激情"的文化,與客戶和合作伙伴齊心協(xié)力一起成長,共同發(fā)展。

在如今高并發(fā)、分布式大行其道的今天,如果你還只會單體項目,那未免也太落伍了。撇開技術(shù)落伍、受人恥笑外(臉皮厚的人根本不在乎恥笑),更為現(xiàn)實的問題是:如果你是剛進入職場的新人,即將面臨找工作,估計連面試機會都沒有;如果你是已經(jīng)在職的人士,不知曉分布式的各種成人姿勢,那你也只有在公司任人玩弄的份。說到分布式這么重要,那今天我作為一個潛伏IT圈多年的老將,跟大家分享下分布式下的分布式鎖的各種成人姿勢,注意是成人哦,未成年人勿入。

二、問題現(xiàn)場還原—秒殺系統(tǒng)下單功能

1.MySQL數(shù)據(jù)庫有2張表:stock(庫存表) ,stock_order(訂單表)。

2.后臺通過spring boot構(gòu)建下單的業(yè)務(wù)接口(下單流程=查庫存–下單–減庫存)。

3.打開瀏覽器正常業(yè)務(wù)流程再現(xiàn),刷新多少次,賣出多少份皮蛋粥,沒毛病。

4.使用壓測工具(ab/jemter/loaderrunner)進行壓力測試ab -n 100 -c 100 http://127.0.0.1:8080/second-kill3/skill/order/123456

5.再次打開瀏覽器查看庫存

各位看官,看到這個結(jié)果是不是有一種蛋碎一地的感覺?。?! 怎么可能10000份皮蛋粥可以賣出(9989+109),如果你感覺奇怪,那說明你的技術(shù)已經(jīng)out了。好了到此場景還原就到此結(jié)束。接下來給各位介紹下解決這種問題的各種姿勢。

三、姿勢一:synchronized

了解多線程的同學肯定會想到,并發(fā)線程安全問題,可以用jdk同步工具synchronized解決。正確的說法給大家更正下,叫做數(shù)據(jù)庫丟失更新。能想到這里的我算你有點社會實踐姿勢,但是效果如何,請看:

1.給下單方法加synchronized,做同步。

2.繼續(xù)壓力測試

ab -n 100 -c 100 http://127.0.0.1:8080/second-kill3/skill/order/123456

3.synchronized姿勢總結(jié):

1)是一種解決方案。

2)synchronized無法實現(xiàn)細粒度的鎖。

在下單的方法中加synchronized會將所有商品下單都做同步,如果另外一件商品并沒有很高并發(fā)量。也會導致很請求 很慢,鎖的粒度太大。

3)只適合單點情況。(而現(xiàn)實是高并發(fā)、分布式集群當?shù)溃?/p>

四、姿勢二:分布式鎖

接下來是我們的主角:分布式鎖登場了。

分布式鎖的三種實現(xiàn)方式:數(shù)據(jù)庫分布式鎖、redis分布式鎖、zookeeper分布式鎖。今天打算給大家介紹下redis分布式鎖的實現(xiàn)方式。

1.安裝redis【不知道怎么安裝的,請咨詢我的官方秘書度娘】

2.maven工程中導入spring-redis依賴。

org.springframework.boot

spring-boot-starter-data-redis

3.編寫redisLock實現(xiàn)加鎖與解鎖

org.springframework.boot spring-boot-starter-data-redis

3.編寫redisLock實現(xiàn)加鎖與解鎖

/**

加鎖

@param key

@param value 當前時間+超時時間

@return

*/

public static boolean lock (String key ,String value){

//setIfAbsent=setNX 如果不存在,就設(shè)置值并返回true,否返回false

//1,加鎖成功 if(redisTemplate.opsForValue().setIfAbsent(key,value)){ return true; }

//2,避免死鎖(線程1加鎖成功,結(jié)果在解鎖前出現(xiàn)異常,沒有解鎖,導致死鎖)

//2.1獲取過期時間 StringcurrentValue=redisTemplate.opsForValue().get(key);

//2.2判斷過期時間于當前時間的關(guān)系

if(!StringUtils.isEmpty(currentValue)

&&Long.parseLong(currentValue)

}

}

//3,加鎖失敗 t2結(jié)束 返回false

return false;

}

/**

解鎖

@param key

@param value

*/

public void unLock(String key,String value){

try {

String currentValue = redisTemplate.opsForValue().get(key);

if(!StringUtils.isEmpty(currentValue)&¤tValue.equals(value)){

redisTemplate.opsForValue().getOperations().delete(key);

}

}catch (Exception e){

log.error("【redis分布式鎖】 解鎖異常");

}

}

4.下單方法加鎖、解鎖

@Override

public void orderProductMockDiffUser(String productId) throws Exception {

//【加鎖】

long time = System.currentTimeMillis()+TIMEOUT;

if(!redisLock.lock(productId,String.valueOf(time))){

throw new Exception(“人也太多了,換個姿勢在試試,~~~~”);

}

//1.查詢該商品庫存,為0則結(jié)束活動

int stockNum = stock.get(productId);

if(stockNum==0){

throw new Exception(“活動結(jié)束”);

}else{

//2.下單(模擬不同的用戶openid 不同)

orders.put(KeyUtil.genUniqueKey(),productId);

//3.減庫存

stockNum-=1;

try {

Thread.sleep(100);

}catch (Exception e){

e.printStackTrace();

}

stock.put(productId,stockNum);

}

//3.解鎖

redisLock.unLock(productId,String.valueOf(time));

}

5.redis姿勢總結(jié):

1)鎖的粒度小。(多個商品同時秒殺不會阻塞)

2)適合高并發(fā),分布式集群部署。

好啦,今天的內(nèi)容就到此結(jié)束了,希望對大家理解分布式鎖有所幫助。


網(wǎng)站標題:【新夢想老師分享】分布式鎖的正確"姿勢"
網(wǎng)頁URL:http://weahome.cn/article/ieojjd.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部