java接口并發衡量_java 后端設計高并發接口總結

如何設置高并發接口

一、并發隊列的選擇

二、請求接口的合理設計

三、高并發下的數據安全

3.1 超發的原因

3.2 悲觀鎖思路

3.3 FIFO隊列思路

3.4 樂觀鎖思路

一、并發隊列的選擇

Java的并發包提供了三個常用的并發隊列實現,分別是:ArrayBlockingQueue、ConcurrentLinkedQueue 和 LinkedBlockingQueue 。

ArrayBlockingQueue是初始容量固定的阻塞隊列,我們可以用來作為數據庫模塊成功競拍的隊列,比如有10個商品,那么我們就設定一個10大小的數組隊列。

ConcurrentLinkedQueue使用的是CAS原語無鎖隊列實現,是一個異步隊列,入隊的速度很快,出隊進行了加鎖,性能稍慢。

LinkedBlockingQueue也是阻塞的隊列,入隊和出隊都用了加鎖,當隊空的時候線程會暫時阻塞。

在請求預處理階段,由于我們的系統入隊需求要遠大于出隊需求,一般不會出現隊空的情況,所以我們可以選擇

ConcurrentLinkedQueue來作為我們的請求隊列實現

二、請求接口的合理設計

一個秒殺或者搶購頁面,通常分為2個部分,一個是靜態的HTML等內容,另一個就是參與秒殺的Web后臺請求接口。

通常靜態HTML等內容,是通過CDN的部署,一般壓力不大,核心瓶頸實際上在后臺請求接口上。這個后端接口,必須能夠支持高并發請求,同時,非常重要的一點,必須盡可能“快”,在最短的時間里返回用戶的請求結果。為了實現盡可能快這一點,接口的后端存儲使用內存級別的操作會更好一點。仍然直接面向MySQL之類的存儲是不合適的,如果有這種復雜業務的需求,都建議采用異步寫入。當然,也有一些秒殺和搶購采用“滯后反饋”,就是說秒殺當下不知道結果,一段時間后才可以從頁面中看到用戶是否秒殺成功。但是,這種屬于“偷懶”行為,同時給用戶的體驗也不好,容易被用戶認為是“暗箱操作”。

三、高并發下的數據安全

我們知道在多線程寫入同一個文件的時候,會存現“線程安全”的問題(多個線程同時運行同一段代碼,如果每次運行結果和單線程運行的結果是一樣的,結果和預期相同,就是線程安全的)。如果是MySQL數據庫,可以使用它自帶的鎖機制很好的解決問題,但是,在大規模并發的場景中,是不推薦使用MySQL的。秒殺和搶購的場景中,還有另外一個問題,就是“超發”,如果在這方面控制不慎,會產生發送過多的情況。我們也曾經聽說過,某些電商搞搶購活動,買家成功拍下后,商家卻不承認訂單有效,拒絕發貨。這里的問題,也許并不一定是商家奸詐,而是系統技術層面存在超發風險導致的。

3.1 超發的原因

假設某個搶購場景中,我們一共只有100個商品,在最后一刻,我們已經消耗了99個商品,僅剩最后一個。這個時候,系統發來多個并發請求,這批請求讀取到的商品余量都是99個,然后都通過了這一個余量判斷,最終導致超發。(同文章前面說的場景),在下面的這個圖中,就導致了并發用戶B也“搶購成功”,多讓一個人獲得了商品。這種場景,在高并發的情況下非常容易出現。

57c4baf0ff913b46402bf4480fc3050e.png

3.2 悲觀鎖思路

解決線程安全的思路很多,可以從“悲觀鎖”的方向開始討論。

悲觀鎖,也就是在修改數據的時候,采用鎖定狀態,排斥外部請求的修改。遇到加鎖的狀態,就必須等待。

28618ce0fd80dceb14b85879855e2d91.png

雖然上述的方案的確解決了線程安全的問題,但是,別忘記,我們的場景是“高并發”。也就是說,會很多這樣的修改請求,每個請求都需要等待“鎖”,某些線程可能永遠都沒有機會搶到這個“鎖”,這種請求就會死在那里。同時,這種請求會很多,瞬間增大系統的平均響應時間,結果是可用連接數被耗盡,系統陷入異常。

3.3 FIFO隊列思路

那好,那么我們稍微修改一下上面的場景,我們直接將請求放入隊列中的,采用FIFO(First Input First Output,先進先出),這樣的話,我們就不會導致某些請求永遠獲取不到鎖。看到這里,是不是有點強行將多線程變成單線程的感覺哈。

6844903974206701581

08087e191c94728fc3eba3ef1e76d73f.png

然后,我們現在解決了鎖的問題,全部請求采用“先進先出”的隊列方式來處理。那么新的問題來了,高并發的場景下,因為請求很多,很可能一瞬間將隊列內存“撐爆”,然后系統又陷入到了異常狀態。或者設計一個極大的內存隊列,也是一種方案,但是,系統處理完一個隊列內請求的速度根本無法和瘋狂涌入隊列中的數目相比。也就是說,隊列內的請求會越積累越多,最終Web系統平均響應時候還是會大幅下降,系統還是陷入異常。

3.4 樂觀鎖思路

這個時候,我們就可以討論一下“樂觀鎖”的思路了。樂觀鎖,是相對于“悲觀鎖”采用更為寬松的加鎖機制,大都是采用帶版本號(Version)更新。實現就是,這個數據所有請求都有資格去修改,但會獲得一個該數據的版本號,只有版本號符合的才能更新成功,其他的返回搶購失敗。這樣的話,我們就不需要考慮隊列的問題,不過,它會增大CPU的計算開銷。但是,綜合來說,這是一個比較好的解決方案。

b83aa4baab80a2f2b4508e9b94b7513f.png

有很多軟件和服務都“樂觀鎖”功能的支持,例如Redis中的watch就是其中之一。通過這個實現,我們保證了數據的安全。

最后

歡迎大家有興趣的可以關注我的公眾號【java小瓜哥的分享平臺】,文章都會在里面更新,還有各種java的資料都是免費分享的。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/378623.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/378623.shtml
英文地址,請注明出處:http://en.pswp.cn/news/378623.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

兩倍---C++

【問題描述】給定n個不同的正整數,你的任務是計算這些數里面有多少個數對滿足:數對中一個數是另一個數的兩倍,比如給定1 4 3 2 9 7 18 22,得到的答案是3,因為2是1的兩倍,4是2的兩倍,18是9的兩倍…

java bitset_Java BitSet cardinality()方法與示例

java bitsetBitSet類cardinality()方法 (BitSet Class cardinality() method) cardinality() method is available in java.util package. cardinality()方法在java.util包中可用。 cardinality() method is used to return the cardinality (i.e. the number of bits is set t…

LeetCode: Merge k Sorted Lists

自己寫的太復雜了,一開始想的是給開始的lists頭們排序,然后從這個序列的第一個抽出來,然后再重新用二分法進行排序,不過這個方法large超時了,看了網上的發現還是用很土地方法用一個for循環從前兩個開始merge到最后&…

JAVA 取得當前目錄的路徑

在寫java程序時不可避免要獲取文件的路徑...總結一下,遺漏的隨時補上 1.可以在servlet的init方法里 String path getServletContext().getRealPath("/"); 這將獲取web項目的全路徑 例如 :E:/eclipseM9/workspace/tree/ tree是我web項目的根目錄 2.你也可以隨時在任意…

golang mysql curd_Go 語言操作 MySQL 之 CURD 操作

本文轉載于SegmentFault社區作者:Meng小羽MySQL 是目前開發中最常見的關系型數據庫,使用 Go 語言進行操控數據庫需要使用 Go 自帶database/sql和驅動go-sql-driver/mysql來實現。創建好 Go 項目,需要引用驅動依賴:go get -u githu…

02.1-元素定位(find)

常用的一些方法 一、導包 from selenium import webdriver二、打開火狐(空白頁) b webdriver.Firefox()三、跳轉到指定的網站 b.get(https://www.baidu.com/)四、將瀏覽器頁面最大化 b.maximize_window()五、通過F12可查看當前的貼吧為超鏈接形式 …

快速傅里葉變換(FFT)——按時間抽取DIT的基

目錄【1】前言1、DIF計算量2、利用性質改善【2】公式推導1、N 到 2*N/2a、分解原序列b、分解后的DFT變換c、一系列化簡操作之后d、蝶形信號流e、計算量總結2、N/2 到 2*N/4a、分解X2(k)序列b、蝶形信號流(2列)3、N/4 到 2*N/8a、蝶形信號流(3…

Python字符串| 帶示例的format()方法

String.format()方法 (String.format() Method) format() method is used to format the string (in other words - we can say to achieve the functionality like printf() in C language). format()方法用于格式化字符串(換句話說,我們可以說實現了C語言中類似于…

PLSQL Developer使用技巧

1、PL/SQL Developer記住登陸密碼在使用PL/SQL Developer時,為了工作方便希望PL/SQL Developer記住登錄Oracle的用戶名和密碼;設置方法:PL/SQL Developer 7.1.2 ->tools->Preferences->Oracle->Logon History , “St…

3月份的總結

租房子找了個黑中介,各種扣錢,合租的違約了,押金不要了直接一走了之,水費我們承擔,中介這會兒又把責任推得一干二凈,還耍小聰明,非說我是兩個人住的,各種費用要交兩份。。。我一時氣…

快速傅里葉變換(FFT)——按頻率抽取DIF的基

目錄【1】回顧DIT【2】算法原理【3】運算特點【1】回顧DIT https://blog.csdn.net/qq_42604176/article/details/105559756 【2】算法原理 設序列點數:N2^M,M為正整數。將輸入序列按照前一半、后一半分開。(并非按照奇偶分) 由于&#xf…

02.2-元素定位(XPath)

XML路徑語言用來確定XML文檔中某部分位置的語言XPath用于在XML文檔中通過元素和屬性進行導航XPath遵守W3C標準XPath節點類型: 元素、屬性、文本、命名空間、指令處理、注釋、文檔 通過路徑表達式從XML文檔中選取節點或節點設置 表達式結果說明/xxx選取根節點xxx/xx…

android ImageView 之 android:scaleTye=

原文:http://juliaailse.iteye.com/blog/1409317 1、scaleType“matrix” 是保持原圖大小、從左上角的點開始,以矩陣形式繪圖。 2、scaleType“fitXY” 是將原圖進行橫方向(即XY方向)的拉伸后繪制的。 3、scaleType“fitStart…

acquire方法_Python鎖類| 帶有示例的acquire()方法

acquire方法Python Lock.acquire()方法 (Python Lock.acquire() Method) acquire() is an inbuilt method of the Lock class of the threading module in Python. acquisition()是Python中線程模塊的Lock類的內置方法。 This method is used to acquire a lock, either block…

VSS2008 安裝silverlight3.0步驟

需要的Q我359273753 我是新手不知道在哪里上傳附件 汗一個轉載于:https://www.cnblogs.com/ganler1988/archive/2011/03/17/1987367.html

php字符串對象,PHP字符串到對象名稱

好的我有一個字符串……$a_string "Product";我想在調用這樣的對象時使用這個字符串:$this->$a_string->some_function();狄更斯如何動態調用該對象?(不要以為我在PHP 5心中)解決方法:所以你要使用的代碼是:$a_string &quo…

莫比烏斯函數---C++

【問題描述】 莫比烏斯函數,數論函數,由德國數學家和天文學家莫比烏斯(Mobius,1790-1868)提出。梅滕斯(Mertens)首先使用μ(n)作為莫比烏斯函數的記號。而據說,高斯(Gauss)比莫比烏斯早三十年就曾考慮過這個函數。莫比烏斯函數在數…

Opencv——findContours函數再探(由輪廓聯想連通域)

目錄關于調參的一些思考分析圖像的一些角度面積、周長、矩形度、圓形度、寬長比例1:找出汽車輪轂圓孔(從輪廓和連通域兩個角度)例2:找出芯片中間正方形物體例3:桌面上橘色物體總結關于調參的一些思考 合理的參數設置&…

stl vector 函數_vector :: crend()函數以及C ++ STL中的示例

stl vector 函數C vector :: crend()函數 (C vector::crend() function) vector::crend() is a library function of "vector" header, it is used to get the first element of a vector from reverse ending, it returns a const reverse iterator pointing to th…

.Net DateTime.ToString 格式化輸出 (轉載)

原文 雖然 System.DateTime 本身已經具有了不少現成的格式化輸出,例如: ToLongDateString, ToShortTimeString, ToUniversalTime 等,但是卻遠遠不能滿足我們實際的需要,這就要用到了 DateTime.ToString,就要提到 DateT…