国产亚洲精品福利在线无卡一,国产精久久一区二区三区,亚洲精品无码国模,精品久久久久久无码专区不卡

當(dāng)前位置: 首頁(yè) > news >正文

外貿(mào)論壇有哪些平臺(tái)抖音seo搜索優(yōu)化

外貿(mào)論壇有哪些平臺(tái),抖音seo搜索優(yōu)化,域名出售平臺(tái),西安做網(wǎng)站微信公司哪家好前言: 在Java后端業(yè)務(wù)中, 如果我們開(kāi)啟了均衡負(fù)載模式,也就是多臺(tái)服務(wù)器處理前端的請(qǐng)求,就會(huì)產(chǎn)生一個(gè)問(wèn)題:多臺(tái)服務(wù)器就會(huì)有多個(gè)JVM,多個(gè)JVM就會(huì)導(dǎo)致服務(wù)器集群下的并發(fā)問(wèn)題。我們?cè)谶@里提出的解決思路是把…

前言:

? ? ? 在Java后端業(yè)務(wù)中,?如果我們開(kāi)啟了均衡負(fù)載模式,也就是多臺(tái)服務(wù)器處理前端的請(qǐng)求,就會(huì)產(chǎn)生一個(gè)問(wèn)題:多臺(tái)服務(wù)器就會(huì)有多個(gè)JVM,多個(gè)JVM就會(huì)導(dǎo)致服務(wù)器集群下的并發(fā)問(wèn)題。我們?cè)谶@里提出的解決思路是把鎖交給Redis來(lái)實(shí)現(xiàn),因?yàn)镽edis是單線程的。而最基礎(chǔ)的Redis解決集群模式下的并發(fā)問(wèn)題的核心解決方案是使用Setnx構(gòu)造分布式鎖,下文來(lái)讓我們?cè)敿?xì)的看一下過(guò)程。

目錄

前言:

核心思路:?

具體業(yè)務(wù)邏輯:

業(yè)務(wù)問(wèn)題解決思路

1.選擇加鎖問(wèn)題:

2.Redis分布式鎖的誤刪問(wèn)題:

3,如何保證刪除鎖代碼的原子性?

業(yè)務(wù)雜項(xiàng)知識(shí)點(diǎn):

1.Spring mvc中的事務(wù)失效引起的并發(fā)問(wèn)題:

2.包裝類與基本數(shù)據(jù)類型的差異:

總結(jié):


?

核心思路:?

?其實(shí)整個(gè)爆改過(guò)程的思路都很清楚,我們先來(lái)解釋一下SETNX的作用:

SETNX key value

SETNX命令的作用是:只有當(dāng)指定的鍵名?key?不存在時(shí),將鍵值對(duì)存儲(chǔ)到Redis數(shù)據(jù)庫(kù)中。如果鍵名?key?已經(jīng)存在,則不執(zhí)行任何操作。

那么整體的核心思路就是:讓當(dāng)前線程嘗試先創(chuàng)建A再執(zhí)行業(yè)務(wù)邏輯代碼,如果A不存在,就進(jìn)行創(chuàng)建,并執(zhí)行相關(guān)業(yè)務(wù)邏輯,業(yè)務(wù)邏輯執(zhí)行完畢后釋放A;如果A存在,那么說(shuō)明此時(shí)有其他的線程在執(zhí)行業(yè)務(wù)邏輯代碼,則拒絕當(dāng)前線程執(zhí)行業(yè)務(wù)邏輯(掛起線程)

其實(shí)就是通過(guò)SETNX構(gòu)造了一個(gè)唯一數(shù)據(jù),并且把這個(gè)數(shù)據(jù)作為鎖。這種思路使得我們的鎖不再局限于某一個(gè)JAVA對(duì)象,從而避開(kāi)了synchronized只能在JVM內(nèi)部生效。解決了集群架構(gòu)下多JVM上鎖困難的困境

具體業(yè)務(wù)邏輯:

本次的具體業(yè)務(wù)應(yīng)用場(chǎng)景是優(yōu)惠卷秒殺場(chǎng)景,簡(jiǎn)單的來(lái)講:就是商家發(fā)放優(yōu)惠卷,用戶進(jìn)行搶購(gòu)。而在優(yōu)惠卷秒殺業(yè)務(wù)中,我們需要注意的是一人一單問(wèn)題。一人一單就是一個(gè)用戶只允許下一單。而我們本項(xiàng)目的背景是允許多端登錄。我們可以想一想這個(gè)問(wèn)題的核心問(wèn)題:如果多端登錄,在服務(wù)器集群架構(gòu)的模式下,如果我們還是傳統(tǒng)模式加鎖,就會(huì)出現(xiàn)這個(gè)問(wèn)題

用戶A同時(shí)登錄的電腦和手機(jī),在以前的模式下:我們是簡(jiǎn)單粗暴的給一人一單核心代碼直接解鎖。但這樣做有兩個(gè)問(wèn)題:

1.如果直接加鎖,那么也就是說(shuō)程序的并發(fā)性大大降低,我們一次只能處理一個(gè)用戶的優(yōu)惠卷訂單,效率大大降低。

2.如果是在集群模式下,傳統(tǒng)的鎖只能在一個(gè)JVM內(nèi)生效,并不能跨JVM。如果用戶的電腦購(gòu)買優(yōu)惠卷請(qǐng)求進(jìn)入到了服務(wù)器A,而用戶的手機(jī)購(gòu)買優(yōu)惠卷請(qǐng)求進(jìn)入到了服務(wù)器B,那么就有可能造成優(yōu)惠卷超賣的情況。

總結(jié)一下優(yōu)惠卷超賣場(chǎng)景的業(yè)務(wù)邏輯

  1. 查詢優(yōu)惠卷是否存在
  2. 查詢優(yōu)惠卷是否在售賣時(shí)間
  3. 查詢當(dāng)前優(yōu)惠卷是否還有庫(kù)存
  4. 查詢用戶是否已經(jīng)下過(guò)單(如果有直接返回給前端Result,封裝消息類)
  5. 扣減優(yōu)惠卷庫(kù)存
  6. 創(chuàng)建訂單ID
  7. 返回訂單號(hào)給前端
  8. 封裝訂單相關(guān)信息,更新數(shù)據(jù)庫(kù)

在這幾步中,從4-8步就是一人一單問(wèn)題,而解決優(yōu)惠卷秒殺問(wèn)題,大部分情況就是在解決這個(gè)問(wèn)題。

業(yè)務(wù)問(wèn)題解決思路

我們來(lái)一步一步看當(dāng)前有哪些問(wèn)題需要我們解決:

1.選擇加鎖問(wèn)題:

在我們最開(kāi)始的加鎖中,我們選擇的是synchronized關(guān)鍵字,但是它會(huì)導(dǎo)致程序的并發(fā)性大大降低。并且無(wú)法跨JVM容器生效。

我們?yōu)榱私鉀Qsynchronized關(guān)鍵字無(wú)法跨JVM容器生效,采用了SETNX關(guān)鍵字。通過(guò)這種方法,我們解決了鎖跨JVM容器生效。

synchronized 是基于JVM層面的同步機(jī)制,它會(huì)鎖定整個(gè)方法,而且它的作用范圍限定在單個(gè)JVM內(nèi)。在分布式系統(tǒng)或者集群環(huán)境中,synchronized 不能跨JVM工作,因此不適合作為分布式鎖使用。而分布式鎖 simpleRedisLock 是基于Redis實(shí)現(xiàn)的,可以跨多個(gè)應(yīng)用實(shí)例工作,適用于分布式系統(tǒng)。

但是它本質(zhì)上和synchronized關(guān)鍵字的作用一樣,并沒(méi)有解決程序的并發(fā)性大大降低的問(wèn)題。只不過(guò)以前我們是通過(guò)synchronized關(guān)鍵字?jǐn)r截線程,現(xiàn)在是通過(guò)SETNX攔截線程。

那么讓我們來(lái)逆推一下思路,加鎖是為了解決兩個(gè)問(wèn)題:

  1. 同一用戶在不同端多次購(gòu)買的相同優(yōu)惠卷的行為
  2. 不同用戶同時(shí)購(gòu)買同一優(yōu)惠卷的行為。

而我們可以先來(lái)優(yōu)化一下同一用戶在不同端多購(gòu)買的行為。按照我們之前的思路是不管三七二十一就上鎖。如圖所示可以理解為:

但是我們真的有這個(gè)必要嘛?我們仔細(xì)想一想:如果只是為了避免同一用戶在不同端多次購(gòu)買的相同優(yōu)惠卷,那么我們只需要針對(duì)這個(gè)用戶加鎖不就好了嘛?

?也就是說(shuō):現(xiàn)在我們?cè)O(shè)計(jì)的鎖,應(yīng)該是只會(huì)攔截同一個(gè)用戶的多次登錄,而不攔截多個(gè)用戶的并發(fā)登錄。如圖所示可以理解為:

我們從代碼層面解釋一下:我們利用SETNX創(chuàng)建key的時(shí)候,將key設(shè)置為USERID。那么此時(shí)就會(huì)出現(xiàn)兩種情況:

1.同一用戶多端登錄發(fā)送購(gòu)票請(qǐng)求,由于SETNX創(chuàng)建KEY的時(shí)候是根據(jù)UserID創(chuàng)建的,因此只能有一個(gè)端創(chuàng)建key成功,實(shí)現(xiàn)了為同一用戶加鎖,避免多端登錄購(gòu)票。

2.不同的用戶由于UserID不同,因此SETNX創(chuàng)建KEY的時(shí)候不會(huì)失敗,也就是說(shuō)不會(huì)被攔截。

也就是說(shuō):我們通過(guò)根據(jù)UserID構(gòu)造key的方式,實(shí)現(xiàn)了為每個(gè)用戶加鎖,提高了程序的并發(fā)性能。

我們?cè)賮?lái)解決一下:多個(gè)用戶同時(shí)購(gòu)買同一優(yōu)惠卷的問(wèn)題。我們?cè)賮?lái)轉(zhuǎn)變一下角度:之所以要處理多個(gè)用戶同時(shí)購(gòu)買同一優(yōu)惠卷,是因?yàn)闀?huì)存在超賣問(wèn)題。而我們?nèi)绾纬思渔i之外,還有沒(méi)有其他的方法解決超賣問(wèn)題呢?

答案是有的.我們?cè)诿恳淮慰蹨p庫(kù)存的時(shí)候,都同步判斷一下當(dāng)前數(shù)據(jù)庫(kù)中優(yōu)惠卷庫(kù)存是否大于0不就好了嘛!

當(dāng)然,這里要保證判斷庫(kù)存和扣減庫(kù)存的原子性,不可以被打斷。

其實(shí)這里的思路就是CAS算法,即Compare And Swap

那么選擇加鎖問(wèn)題我們已經(jīng)解決了,為了優(yōu)化普通模式下加鎖的無(wú)法跨JVM容器拷打并發(fā)性的問(wèn)題,我們采用了以下兩個(gè)步驟:

  • 無(wú)法跨容器:使用Redis中的SETNX來(lái)保證鎖可跨JVM容器
  • 并發(fā)性差:利用userID構(gòu)造每個(gè)用戶專屬的鎖,并且通過(guò)數(shù)據(jù)庫(kù)操作維護(hù)多用戶下單超賣問(wèn)題。

此時(shí)我們用流程圖來(lái)展示一下當(dāng)前的執(zhí)行邏輯:

當(dāng)然了,為了避免死鎖的出現(xiàn),我們要為SETNX構(gòu)造出的鍵值對(duì)設(shè)置過(guò)期時(shí)間,防止死鎖的出現(xiàn)。

而接下來(lái)的問(wèn)題也就是我們要著重介紹的一個(gè)問(wèn)題:

2.Redis分布式鎖的誤刪問(wèn)題:

此處我們說(shuō)的是同一用戶多端登錄引發(fā)的并發(fā)性問(wèn)題,而不同用戶之間由于構(gòu)造的時(shí)候key就不一樣,因此不存在誤刪問(wèn)題。

在我們前面構(gòu)造的業(yè)務(wù)邏輯中,理想的狀態(tài)應(yīng)該是:

在理想狀態(tài)下,多段登錄可以正確的創(chuàng)建和釋放鎖,維護(hù)程序的并發(fā)性,而在我們的業(yè)務(wù)邏輯中,可能會(huì)出現(xiàn)如下異常情況:

這段異常簡(jiǎn)單的來(lái)講:線程1的阻塞使得線程1所創(chuàng)建的用戶鎖被超時(shí)釋放,此時(shí)Redis中并沒(méi)有針對(duì)當(dāng)前用戶的鎖,當(dāng)前用戶再發(fā)起一個(gè)線程2線程2獲取到鎖。而線程1此時(shí)阻塞結(jié)束,開(kāi)始執(zhí)行業(yè)務(wù)和最后刪除鎖的操作,導(dǎo)致線程2創(chuàng)建的當(dāng)前用戶鎖被刪除。此時(shí)線程2在執(zhí)行自己的業(yè)務(wù),但是整個(gè)redis中已經(jīng)無(wú)針對(duì)當(dāng)前用戶的鎖了。線程3此時(shí)嘗試獲取鎖,獲取成功。那么在這種環(huán)境下,線程1,2,3都獲取到了鎖并且執(zhí)行了買票業(yè)務(wù)。

這種業(yè)務(wù)場(chǎng)景雖然少見(jiàn),但仍是我們要解決的問(wèn)題。

而解決的思路也很簡(jiǎn)單:主要的思路:設(shè)置鎖標(biāo)識(shí),讓每個(gè)線程只能刪除自己的鎖?

也就是說(shuō):以前我們利用SETNX創(chuàng)建鎖的時(shí)候,是不管鎖的value值的,現(xiàn)在為了解決鎖的誤刪問(wèn)題,我們要給value中賦值,使其成為鎖標(biāo)識(shí)。

我們看看代碼:

創(chuàng)建鎖:

刪除鎖:

但是這樣就對(duì)了嘛??

其實(shí)是不對(duì)的! 這是因?yàn)槲覀冊(cè)趗nlock里面執(zhí)行了多條語(yǔ)句,可能在獲取鎖的標(biāo)識(shí)的時(shí)候,還沒(méi)來(lái)得及執(zhí)行delete語(yǔ)句,線程就又被阻塞了,此時(shí)就又會(huì)發(fā)生我們之前說(shuō)的誤刪問(wèn)題。

3,如何保證刪除鎖代碼的原子性?

在這里我們使用的是lua腳本。Redis提供了lua腳本功能,在一個(gè)腳本中編寫多條Redis命令,確保多條命令執(zhí)行時(shí)的原子性。

關(guān)于lua腳本的書寫我們這里不做具體介紹,感興趣的同學(xué)可以自學(xué),lua是基于c語(yǔ)言實(shí)現(xiàn)的,他的語(yǔ)法結(jié)構(gòu)很簡(jiǎn)單。

Lua 教程 (w3schools.cn)icon-default.png?t=N7T8https://www.w3schools.cn/lua/index.asp

將之前的unlock中的redis操作轉(zhuǎn)化為lua腳本,然后再交給redis執(zhí)行。

我們來(lái)看看代碼:

通過(guò)這種方式,我們就確保了多條Redis命令的原子性,解決了刪除鎖代碼的原子性問(wèn)題。

業(yè)務(wù)雜項(xiàng)知識(shí)點(diǎn):

1.Spring mvc中的事務(wù)失效引起的并發(fā)問(wèn)題:

在代碼框架設(shè)計(jì)的時(shí)候,我把4-8過(guò)程單獨(dú)拉出來(lái)封裝了一個(gè)方法:

封裝部分代碼:?

為了保證扣減庫(kù)存的時(shí)候執(zhí)行的多條SQL語(yǔ)句的原子性,我們加上了@Transactional注解。然后在獲取鎖后執(zhí)行業(yè)務(wù)邏輯代碼的時(shí)候調(diào)用這個(gè)方法。

但這也就是一個(gè)坑點(diǎn):Spring mvc中的事務(wù)是會(huì)失效的。?

????????在Spring框架中,聲明式事務(wù)管理依賴于AOP(面向切面編程)。當(dāng)我們?cè)谝粋€(gè)方法上使用@Transactional注解時(shí),Spring將創(chuàng)建一個(gè)代理對(duì)象來(lái)包裝原始的Bean。這個(gè)代理對(duì)象會(huì)在方法調(diào)用前后添加事務(wù)管理的邏輯,如開(kāi)啟和關(guān)閉事務(wù),以及在發(fā)生異常時(shí)進(jìn)行回滾操作。

如果直接調(diào)用同一個(gè)類中的另一個(gè)@Transactional方法,由于是內(nèi)部調(diào)用,并不會(huì)經(jīng)過(guò)代理對(duì)象,因此事務(wù)管理相關(guān)的邏輯不會(huì)被執(zhí)行。這就是為什么通常建議將事務(wù)管理放在服務(wù)層(Service Layer),并且只通過(guò)注入的方式跨類調(diào)用事務(wù)方法,確保每次調(diào)用都能通過(guò)代理對(duì)象,從而讓AOP能夠正確地應(yīng)用事務(wù)管理的邏輯。

如果不使用Spring AOP代理機(jī)制,那么@Transactional注解將不會(huì)生效,因?yàn)闆](méi)有任何機(jī)制來(lái)攔截方法調(diào)用并應(yīng)用事務(wù)的邊界。這意味著即使定義了事務(wù),也不會(huì)有實(shí)際的事務(wù)行為發(fā)生,如開(kāi)始新事務(wù)、加入現(xiàn)有事務(wù)或在發(fā)生異常時(shí)回滾事務(wù)。

總結(jié)來(lái)說(shuō),Spring的聲明式事務(wù)管理是通過(guò)AOP代理實(shí)現(xiàn)的,不使用AOP代理將導(dǎo)致事務(wù)失效。要確保事務(wù)能夠正常工作,必須遵循Spring的配置和使用準(zhǔn)則,確保通過(guò)代理對(duì)象對(duì)事務(wù)方法進(jìn)行調(diào)用。

因此在調(diào)用這個(gè)方法時(shí)候,我們不能直接調(diào)用,這種方式是錯(cuò)誤的!?

而應(yīng)該這么調(diào)用:

?

2.包裝類與基本數(shù)據(jù)類型的差異:

當(dāng)我們使用stringRedisTemplate來(lái)操作Redis的時(shí)候,返回值會(huì)有包裝類型,例如Boolean。

但是如果我們直接這樣返回的話,會(huì)出現(xiàn)一個(gè)問(wèn)題:我們要求的返回值類型是boolean,也就是基本數(shù)據(jù)類型。雖然Boolean會(huì)有自動(dòng)拆箱功能,可以自動(dòng)轉(zhuǎn)換為boolean,但是可能會(huì)出現(xiàn)空指針異常!

這是為什么呢?原因很簡(jiǎn)單:Boolean是包裝類,可以存放空值,而在自動(dòng)拆箱的時(shí)候空值會(huì)轉(zhuǎn)變?yōu)榭罩羔?。而基本?shù)據(jù)類型不允許存儲(chǔ)空指針。因此直接拋出空指針異常。

總結(jié):

? ? ? ? 經(jīng)過(guò)本文的講解,我們了解了如何利用Redis實(shí)現(xiàn)一個(gè)簡(jiǎn)單的分布式鎖。而其實(shí)Redis就已經(jīng)為我們提供了一套高性能,高可用的分布式鎖:Redission。在之后的文章我也會(huì)給大家介紹如何使用Redission。

如果我的內(nèi)容對(duì)你有幫助,請(qǐng)點(diǎn)贊,評(píng)論,收藏。創(chuàng)作不易,大家的支持就是我堅(jiān)持下去的動(dòng)力!

http://aloenet.com.cn/news/44364.html

相關(guān)文章:

  • 漣水做網(wǎng)站二十個(gè)優(yōu)化
  • 北海做網(wǎng)站網(wǎng)站建設(shè)哪家好seo技術(shù)博客
  • 路由器做網(wǎng)站主機(jī)要備案嗎外鏈網(wǎng)
  • WordPress源碼帶會(huì)員中心系統(tǒng)排名優(yōu)化哪家專業(yè)
  • 無(wú)錫做網(wǎng)站品牌公司百度人工客服在線咨詢電話
  • 太原做網(wǎng)站的公司網(wǎng)站建設(shè)網(wǎng)絡(luò)推廣是以企業(yè)產(chǎn)品或服務(wù)
  • 網(wǎng)店運(yùn)營(yíng)規(guī)劃如何優(yōu)化關(guān)鍵詞的排名
  • 淘寶做短視頻網(wǎng)站好鏈接買賣價(jià)格
  • 有誰(shuí)做彩票網(wǎng)站嗎廊坊關(guān)鍵詞優(yōu)化報(bào)價(jià)
  • 聚合頁(yè)做的比較好的教育網(wǎng)站軟件定制開(kāi)發(fā)
  • 網(wǎng)站做302跳轉(zhuǎn)的意義什么軟件可以找客戶資源
  • 商丘三合一網(wǎng)站建設(shè)廈門seo推廣優(yōu)化
  • 用舊電腦做網(wǎng)站推廣網(wǎng)站怎么制作
  • 個(gè)人網(wǎng)站備案信息北京網(wǎng)站制作推廣
  • 中信建設(shè)有限責(zé)任公司唐萬(wàn)哩如何提高網(wǎng)站seo排名
  • 網(wǎng)站的功能和特色百度推廣是做什么的
  • 玉樹(shù)市公司網(wǎng)站建設(shè)seo搜外
  • 網(wǎng)站的原型怎么做百度搜索競(jìng)價(jià)排名
  • 網(wǎng)站開(kāi)發(fā)目錄結(jié)構(gòu)百度首頁(yè)排名怎么做到
  • 做ppt模板網(wǎng)站有哪些網(wǎng)站統(tǒng)計(jì)
  • 做自己網(wǎng)站彩票免費(fèi)站長(zhǎng)工具
  • 寶安有效的網(wǎng)站制作站長(zhǎng)域名查詢工具
  • python源碼分享網(wǎng)站百度客服24小時(shí)人工服務(wù)
  • wordpress消息系統(tǒng)滕州網(wǎng)站建設(shè)優(yōu)化
  • 淘寶開(kāi)店網(wǎng)站怎么做網(wǎng)絡(luò)稿件投稿平臺(tái)
  • 可以做照片書的網(wǎng)站百度推廣入口
  • next 主題wordpress谷歌seo招聘
  • 用內(nèi)網(wǎng)穿透做網(wǎng)站可以被收錄嗎淘寶關(guān)鍵詞搜索工具
  • 懷柔網(wǎng)站制作煙臺(tái)seo網(wǎng)絡(luò)推廣
  • 淄博 網(wǎng)站建設(shè)免費(fèi)網(wǎng)站在線客服系統(tǒng)源碼