日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区

您的位置:首頁技術(shù)文章
文章詳情頁

mysql居然還能實現(xiàn)分布式鎖的方法

瀏覽:37日期:2023-10-07 09:06:22
前言

之前的文章中通過電商場景中秒殺的例子和大家分享了單體架構(gòu)中鎖的使用方式,但是現(xiàn)在很多應(yīng)用系統(tǒng)都是相當(dāng)龐大的,很多應(yīng)用系統(tǒng)都是微服務(wù)的架構(gòu)體系,那么在這種跨jvm的場景下,我們又該如何去解決并發(fā)。

單體應(yīng)用鎖的局限性

在進(jìn)入實戰(zhàn)之前簡單和大家粗略聊一下互聯(lián)網(wǎng)系統(tǒng)中的架構(gòu)演進(jìn)。

mysql居然還能實現(xiàn)分布式鎖的方法

在互聯(lián)網(wǎng)系統(tǒng)發(fā)展之初,消耗資源比較小,用戶量也比較小,我們只部署一個tomcat應(yīng)用就可以滿足需求。一個tomcat我們可以看做是一個jvm的進(jìn)程,當(dāng)大量的請求并發(fā)到達(dá)系統(tǒng)時,所有的請求都落在這唯一的一個tomcat上,如果某些請求方法是需要加鎖的,比如上篇文章中提及的秒殺扣減庫存的場景,是可以滿足需求的。但是隨著訪問量的增加,一個tomcat難以支撐,這時候我們就需要集群部署tomcat,使用多個tomcat支撐起系統(tǒng)。

在上圖中簡單演化之后,我們部署兩個Tomcat共同支撐系統(tǒng)。當(dāng)一個請求到達(dá)系統(tǒng)的時候,首先會經(jīng)過nginx,由nginx作為負(fù)載均衡,它會根據(jù)自己的負(fù)載均衡配置策略將請求轉(zhuǎn)發(fā)到其中的一個tomcat上。當(dāng)大量的請求并發(fā)訪問的時候,兩個tomcat共同承擔(dān)所有的訪問量。這之后我們同樣進(jìn)行秒殺扣減庫存的時候,使用單體應(yīng)用鎖,還能滿足需求么?

之前我們所加的鎖是JDK提供的鎖,這種鎖在單個jvm下起作用,當(dāng)存在兩個或者多個的時候,大量并發(fā)請求分散到不同tomcat,在每個tomcat中都可以防止并發(fā)的產(chǎn)生,但是多個tomcat之間,每個Tomcat中獲得鎖這個請求,又產(chǎn)生了并發(fā)。從而扣減庫存的問題依舊存在。這就是單體應(yīng)用鎖的局限性。那我們?nèi)绻鉀Q這個問題呢?接下來就要和大家分享分布式鎖了。

分布式鎖什么是分布式鎖?

那么什么是分布式鎖呢,在說分布式鎖之前我們看到單體應(yīng)用鎖的特點就是在一個jvm進(jìn)行有效,但是無法跨越j(luò)vm以及進(jìn)程。所以我們就可以下一個不那么官方的定義,分布式鎖就是可以跨越多個jvm,跨越多個進(jìn)程的鎖,像這樣的鎖就是分布式鎖。

設(shè)計思路

mysql居然還能實現(xiàn)分布式鎖的方法

由于tomcat是java啟動的,所以每個tomcat可以看成一個jvm,jvm內(nèi)部的鎖無法跨越多個進(jìn)程。所以我們實現(xiàn)分布式鎖,只能在這些jvm外去尋找,通過其他的組件來實現(xiàn)分布式鎖。

上圖兩個tomcat通過第三方的組件實現(xiàn)跨jvm,跨進(jìn)程的分布式鎖。這就是分布式鎖的解決思路。

實現(xiàn)方式

那么目前有哪些第三方組件來實現(xiàn)呢?目前比較流行的有以下幾種:

數(shù)據(jù)庫,通過數(shù)據(jù)庫可以實現(xiàn)分布式鎖,但是高并發(fā)的情況下對數(shù)據(jù)庫的壓力比較大,所以很少使用。 Redis,借助redis可以實現(xiàn)分布式鎖,而且redis的java客戶端種類很多,所以使用方法也不盡相同。 Zookeeper,也可以實現(xiàn)分布式鎖,同樣zk也有很多java客戶端,使用方法也不同。

針對上述實現(xiàn)方式,老貓還是通過具體的代碼例子來一一演示。

基于數(shù)據(jù)庫的分布式鎖

思路:基于數(shù)據(jù)庫悲觀鎖去實現(xiàn)分布式鎖,用的主要是select ... for update。select ... for update是為了在查詢的時候就對查詢到的數(shù)據(jù)進(jìn)行了加鎖處理。當(dāng)用戶進(jìn)行這種行為操作的時候,其他線程是禁止對這些數(shù)據(jù)進(jìn)行修改或者刪除操作,必須等待上個線程操作完畢釋放之后才能進(jìn)行操作,從而達(dá)到了鎖的效果。

實現(xiàn):我們還是基于電商中超賣的例子和大家分享代碼。

咱們還是利用上次單體架構(gòu)中的超賣的例子和大家分享,針對上次的代碼進(jìn)行改造,我們新鍵一張表,叫做distribute_lock,這張表的目的主要是為了提供數(shù)據(jù)庫鎖,我們來看一下這張表的情況。

mysql居然還能實現(xiàn)分布式鎖的方法

由于我們這邊模擬的是訂單超賣的場景,所以在上圖中我們有一條訂單的鎖數(shù)據(jù)。

我們將上一篇中的代碼改造一下抽取出一個controller然后通過postman去請求調(diào)用,當(dāng)然后臺是啟動兩個jvm進(jìn)行操作,分別是8080端口以及8081端口。完成之后的代碼如下:

/** * @author kdaddy@163.com * @date 2021/1/3 10:48 * @desc 公眾號“程序員老貓” */@Service@Slf4jpublic class MySQLOrderService { @Resource private KdOrderMapper orderMapper; @Resource private KdOrderItemMapper orderItemMapper; @Resource private KdProductMapper productMapper; @Resource private DistributeLockMapper distributeLockMapper; //購買商品id private int purchaseProductId = 100100; //購買商品數(shù)量 private int purchaseProductNum = 1; @Transactional(propagation = Propagation.REQUIRED) public Integer createOrder() throws Exception{ log.info('進(jìn)入了方法'); DistributeLock lock = distributeLockMapper.selectDistributeLock('order'); if(lock == null) throw new Exception('該業(yè)務(wù)分布式鎖未配置'); log.info('拿到了鎖'); //此處為了手動演示并發(fā),所以我們暫時在這里休眠1分鐘 Thread.sleep(60000); KdProduct product = productMapper.selectByPrimaryKey(purchaseProductId); if (product==null){ throw new Exception('購買商品:'+purchaseProductId+'不存在'); } //商品當(dāng)前庫存 Integer currentCount = product.getCount(); log.info(Thread.currentThread().getName()+'庫存數(shù)'+currentCount); //校驗庫存 if (purchaseProductNum > currentCount){ throw new Exception('商品'+purchaseProductId+'僅剩'+currentCount+'件,無法購買'); } //在數(shù)據(jù)庫中完成減量操作 productMapper.updateProductCount(purchaseProductNum,'kd',new Date(),product.getId()); //生成訂單 ...次數(shù)省略,源代碼可以到老貓的github下載:https://github.com/maoba/kd-distribute return order.getId(); }}

SQL的寫法如下:

select * from distribute_lock where business_code = #{business_code,jdbcType=VARCHAR} for update

以上為主要實現(xiàn)邏輯,關(guān)于代碼中的注意點:

createOrder方法必須要有事務(wù),因為只有在事務(wù)存在的情況下才能觸發(fā)select for update的鎖。 代碼中必須要對當(dāng)前鎖的存在性進(jìn)行判斷,如果為空的情況下,會報異常

我們來看一下最終運行的效果,先看一下console日志,

8080的console日志情況:

11:49:41 INFO 16360 --- [nio-8080-exec-2] c.k.d.service.MySQLOrderService : 進(jìn)入了方法11:49:41 INFO 16360 --- [nio-8080-exec-2] c.k.d.service.MySQLOrderService : 拿到了鎖

8081的console日志情況:

11:49:48 INFO 17640 --- [nio-8081-exec-2] c.k.d.service.MySQLOrderService : 進(jìn)入了方法

通過日志情況,兩個不同的jvm,由于第一個到8080的請求優(yōu)先拿到了鎖,所以8081的請求就處于等待鎖釋放才會去執(zhí)行,這說明我們的分布式鎖生效了。再看一下完整執(zhí)行之后的日志情況:

8080的請求:

11:58:01 INFO 15380 --- [nio-8080-exec-1] c.k.d.service.MySQLOrderService : 進(jìn)入了方法11:58:01 INFO 15380 --- [nio-8080-exec-1] c.k.d.service.MySQLOrderService : 拿到了鎖11:58:07 INFO 15380 --- [nio-8080-exec-1] c.k.d.service.MySQLOrderService : http-nio-8080-exec-1庫存數(shù)1

8081的請求:

11:58:03 INFO 16276 --- [nio-8081-exec-1] c.k.d.service.MySQLOrderService : 進(jìn)入了方法11:58:08 INFO 16276 --- [nio-8081-exec-1] c.k.d.service.MySQLOrderService : 拿到了鎖11:58:14 INFO 16276 --- [nio-8081-exec-1] c.k.d.service.MySQLOrderService : http-nio-8081-exec-1庫存數(shù)011:58:14 ERROR 16276 --- [nio-8081-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is java.lang.Exception: 商品100100僅剩0件,無法購買] with root cause

java.lang.Exception: 商品100100僅剩0件,無法購買 at com.kd.distribute.service.MySQLOrderService.createOrder(MySQLOrderService.java:61) ~[classes/:na]

很明顯第二個請求由于沒有庫存,導(dǎo)致最終購買失敗的情況,當(dāng)然這個場景也是符合我們正常的業(yè)務(wù)場景的。最終我們數(shù)據(jù)庫的情況是這樣的:

mysql居然還能實現(xiàn)分布式鎖的方法

mysql居然還能實現(xiàn)分布式鎖的方法

很明顯,我們到此數(shù)據(jù)庫的庫存和訂單數(shù)量也都正確了。到此我們基于數(shù)據(jù)庫的分布式鎖實戰(zhàn)演示完成,下面我們來歸納一下如果使用這種鎖,有哪些優(yōu)點以及缺點。

優(yōu)點:簡單方便、易于理解、易于操作。 缺點:并發(fā)量大的時候?qū)?shù)據(jù)庫的壓力會比較大。 建議:作為鎖的數(shù)據(jù)庫和業(yè)務(wù)數(shù)據(jù)庫分開。寫在最后

對于上述數(shù)據(jù)庫分布式鎖,其實在我們的日常開發(fā)中用的也是比較少的。基于redis以及zk的鎖倒是用的比較多一些,本來老貓想把redis鎖以及zk鎖放在這一篇中一起分享掉,但是再寫在同一篇上面的話,篇幅就顯得過長了,因此本篇就和大家分享這一種分布式鎖。源碼大家可以在老貓的github中下載到。地址是:https://github.com/maoba/kd-distribute

到此這篇關(guān)于mysql居然還能實現(xiàn)分布式鎖的方法的文章就介紹到這了,更多相關(guān)mysql 分布式鎖內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!

標(biāo)簽: MySQL 數(shù)據(jù)庫
相關(guān)文章:
日本不卡不码高清免费观看,久久国产精品久久w女人spa,黄色aa久久,三上悠亚国产精品一区二区三区
久久国产精品美女| 欧美精品不卡| 91精品一区二区三区综合在线爱| 国产探花一区在线观看| 国产精品1区在线| 亚洲欧美日本视频在线观看| 亚洲精品高潮| 国产成人久久精品麻豆二区 | 午夜在线播放视频欧美| 亚洲精品一级| 日韩av有码| 日韩综合一区二区三区| 国产v日韩v欧美v| 日韩高清不卡一区| 精品一二三区| 国产精品视频一区二区三区四蜜臂 | 日本成人在线网站| 免费国产亚洲视频| 日韩天堂在线| 国产精品最新| 亚洲欧美视频| 久久三级福利| 日韩精品午夜视频| 国产一区二区三区四区五区| 久久国产精品色av免费看| 在线精品一区二区| 久久一区二区三区喷水| 蜜桃一区二区三区在线观看| 国产免费av国片精品草莓男男| 欧美日韩视频| 欧美二区视频| 欧美午夜精彩| 午夜欧美在线| 国产午夜久久av| 国产精品亚洲人成在99www| 亚洲精品伦理| 视频一区中文字幕| 日韩制服丝袜先锋影音| 国产精品日本| 亚洲三级毛片| 国产一区二区三区亚洲综合| 国产精品久久久久久久免费软件| 国产精品1区| 99久久久国产精品美女| 欧美日韩免费观看视频| 粉嫩av一区二区三区四区五区 | 黄色在线观看www| 亚洲激情国产| 男人天堂欧美日韩| 丰满少妇一区| 亚洲日韩视频| 久久久久美女| 亚洲精品在线a| 国产精品红桃| 亚洲韩日在线| 日本不卡一二三区黄网| 精品黄色一级片| 日本国产亚洲| av资源亚洲| 国产aⅴ精品一区二区四区| 日韩精品专区| 欧美精品97| 久久视频一区| 黄色在线一区| 久久国产欧美| 日韩av一区二| 久久国产88| 久久精品xxxxx| 日韩中文字幕一区二区三区| 欧美激情日韩| 在线日韩av| 国产欧美日韩在线观看视频| 久久久久国产精品一区三寸| 久久中文在线| 久久在线视频免费观看| 日韩三级一区| 成人在线黄色| 综合色就爱涩涩涩综合婷婷| 国产精品成人a在线观看| 午夜一区在线| 国产字幕视频一区二区| 日韩精品高清不卡| 狠狠干综合网| 97精品中文字幕| 国产精品久久观看| 国产精品白丝久久av网站| 日韩av电影一区| 亚洲综合精品四区| 亚洲v天堂v手机在线| 国产亚洲精aa在线看| 国产精品亲子伦av一区二区三区 | 国产精品久久久久久av公交车| 激情婷婷久久| 涩涩av在线| 免费日韩av| 首页国产欧美久久| 奇米亚洲欧美| 国产精品中文字幕亚洲欧美| 亚洲aa在线| 欧美91精品| 国产高清久久| 亚洲一本视频| 国产一区二区视频在线看| 国产精品久久久亚洲一区| 91精品国产成人观看| 黄色日韩精品| 精品美女在线视频| 日韩专区欧美专区| 国产中文欧美日韩在线| 午夜一区在线| 欧美13videosex性极品| 免费久久99精品国产| 精品视频一区二区三区在线观看 | 精品欧美日韩精品| 亚洲日韩中文字幕一区| 美女av在线免费看| 午夜电影一区| 麻豆精品蜜桃| 欧美一级二区| 午夜久久99| 国产欧洲在线| 国产欧美另类| 亚洲一区二区三区四区电影 | 激情综合网五月| 国产精品蜜月aⅴ在线| 欧美一级全黄| 久久精品卡一| 国产一区二区三区久久久久久久久| 鲁大师影院一区二区三区| 亚洲一级少妇| 国产精品白丝av嫩草影院| 日韩精品视频中文字幕| 日韩视频免费| 欧美日韩国产一区二区三区不卡| 国产成人a视频高清在线观看| 国产日本精品| 国产精品麻豆成人av电影艾秋 | 欧美激情亚洲| 欧美啪啪一区| 日本不卡的三区四区五区| 亚洲一区二区三区四区五区午夜 | 久久男人av资源站| 欧美aaaaaa午夜精品| 国产伦精品一区二区三区在线播放| 91国语精品自产拍| 欧美.日韩.国产.一区.二区| 88xx成人免费观看视频库| 国产成人77亚洲精品www| 91嫩草亚洲精品| 国产极品嫩模在线观看91精品| 日韩三级久久| 久久不卡日韩美女| 精品久久影院| 久久久成人网| 亚洲在线国产日韩欧美| 在线免费观看亚洲| 日韩国产成人精品| 国产精品hd| av在线日韩| 午夜国产一区二区| 亚洲毛片在线| 久久久国产精品入口麻豆| 激情久久99| 高清不卡一区| 999国产精品永久免费视频app| 性欧美xxxx免费岛国不卡电影| 中日韩男男gay无套| 日韩高清不卡一区二区| 精品国产三区在线| 国产精品毛片一区二区三区| 日本中文字幕视频一区| 精品成av人一区二区三区| 亚洲女同中文字幕| 国产欧美激情| 91精品日本| 国产精久久一区二区| av中文字幕在线观看第一页| 美女被久久久| 麻豆久久久久久久| 久久亚洲电影| 亚洲精品88| 欧美午夜不卡| 狂野欧美性猛交xxxx| 午夜在线精品偷拍| 中文字幕高清在线播放| 免费在线欧美视频| 欧美亚洲日本精品| 亚洲欧洲美洲国产香蕉| 九色porny丨国产首页在线| 模特精品在线| 午夜av成人| 久久亚洲人体| 国产私拍福利精品视频二区| 欧美专区18| 免费国产自久久久久三四区久久| 欧美三级第一页| 亚洲91在线| 色婷婷成人网| 尹人成人综合网| 一区二区小说|