自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

解決一個(gè)互斥問(wèn)題,系統(tǒng)并發(fā)用戶(hù)數(shù)提升了10倍!

系統(tǒng) 其他OS
對(duì)于接下來(lái)的其他操作(即用戶(hù)提交數(shù)據(jù)過(guò)程中的一些不可拆分的關(guān)鍵業(yè)務(wù)操作),如果操作成功,就提交任務(wù)成功結(jié)束;如果操作失敗,則需要回滾之前的字段插入操作。

互斥鎖在實(shí)現(xiàn)并發(fā)場(chǎng)景下業(yè)務(wù)操作的原子性以及解決互斥訪問(wèn)問(wèn)題方面,是極為有效的手段之一。因其使用方式相對(duì)簡(jiǎn)單且安全,所以在互聯(lián)網(wǎng)的分布式系統(tǒng)以及嵌入式并發(fā)場(chǎng)景中都有著廣泛的應(yīng)用。

然而,若互斥鎖的選擇與使用不當(dāng),極有可能成為系統(tǒng)性能的瓶頸之一。因此,對(duì)互斥鎖進(jìn)行合理優(yōu)化,是系統(tǒng)性能優(yōu)化的重要途徑。我將為你分享一個(gè)互聯(lián)網(wǎng)場(chǎng)景下互斥鎖優(yōu)化的案例。按照優(yōu)化前的軟件實(shí)現(xiàn)、性能瓶頸分析以及優(yōu)化解決方案的思路,帶你深入剖析我是如何優(yōu)化業(yè)務(wù)中的互斥鎖,以及如何將業(yè)務(wù)的 RPS(Requests per second,請(qǐng)求吞吐量)性能指標(biāo)提升 10 倍以上的。

在這個(gè)案例中夠全面了解分析與優(yōu)化互斥鎖的詳細(xì)過(guò)程,從而在業(yè)務(wù)中準(zhǔn)確識(shí)別出哪些場(chǎng)景下的互斥鎖可以?xún)?yōu)化,哪些場(chǎng)景下不可以。此外,你還將掌握一種手動(dòng)實(shí)現(xiàn)事務(wù)的機(jī)制(支持業(yè)務(wù)操作回滾機(jī)制),以此替代業(yè)務(wù)中的互斥鎖,進(jìn)一步優(yōu)化軟件性能。

接下來(lái),我們先看看該案例中業(yè)務(wù)優(yōu)化前的實(shí)現(xiàn)情況以及存在的性能問(wèn)題。

優(yōu)化前的業(yè)務(wù)實(shí)現(xiàn)為什么會(huì)有性能問(wèn)題?

這個(gè)性能優(yōu)化案例的業(yè)務(wù)場(chǎng)景如下:用戶(hù)向在線表單提交一條記錄,該記錄包含眾多字段內(nèi)容。其中,部分字段在插入時(shí)有一個(gè)規(guī)則要求,即不能與已有的字段值重復(fù)。為了便于理解,這里我用一張圖來(lái)描述原業(yè)務(wù)系統(tǒng)中實(shí)現(xiàn)字段插入值不重復(fù)規(guī)則的實(shí)現(xiàn)邏輯,具體情況如下所示。

圖片圖片

可見(jiàn),在該業(yè)務(wù)中使用了一個(gè) Redis 鎖來(lái)實(shí)現(xiàn)互斥訪問(wèn),從而實(shí)現(xiàn)了被加鎖的業(yè)務(wù)邏輯執(zhí)行的原子性,所以這部分計(jì)算邏輯在系統(tǒng)中是串行執(zhí)行的。而被加鎖的業(yè)務(wù)邏輯主要有三個(gè)關(guān)鍵操作,分別是:

一、字段不重復(fù)檢測(cè)

對(duì)插入的字段值進(jìn)行檢測(cè),查看其在數(shù)據(jù)庫(kù)中是否有重復(fù)情況。若出現(xiàn)重復(fù)值,則插入失敗并直接退出;若未出現(xiàn)重復(fù)值,則執(zhí)行下一步操作。在這個(gè)過(guò)程中,系統(tǒng)會(huì)遍歷所有要求值不能重復(fù)的字段項(xiàng),只要其中任何一個(gè)字段項(xiàng)出現(xiàn)值重復(fù),就會(huì)退出。

二、其他操作

即用戶(hù)提交記錄過(guò)程中的一些關(guān)鍵業(yè)務(wù)操作。這些操作具有不能被拆分執(zhí)行且不能被回滾的特點(diǎn)。若操作成功,則執(zhí)行下一步操作;否則,也會(huì)直接退出。

三、所有字段插入

由于上述三個(gè)操作通過(guò)加鎖保證了原子性執(zhí)行,所以前面檢測(cè)的 “字段值不重復(fù)” 的條件仍然有效。在這一步,會(huì)將有的字段進(jìn)行插入。

除此之外,在優(yōu)化前的代碼實(shí)現(xiàn)中,需要進(jìn)行重復(fù)性校驗(yàn)的字段都會(huì)記錄在 Redis 中。所以,圖中的操作 1、操作 3 都是基于 Redis 來(lái)實(shí)現(xiàn)的。

在看完這個(gè)業(yè)務(wù)實(shí)現(xiàn)邏輯圖后,你或許會(huì)感到好奇:這種字段唯一性檢測(cè)機(jī)制為何不使用關(guān)系數(shù)據(jù)庫(kù)中的字段唯一性檢測(cè)機(jī)制來(lái)實(shí)現(xiàn)呢?這確實(shí)是個(gè)好問(wèn)題,我在剛看到這個(gè)業(yè)務(wù)邏輯實(shí)現(xiàn)時(shí)也同樣好奇,后來(lái)深入分析業(yè)務(wù)后才理解其如此實(shí)現(xiàn)的原因。

實(shí)際上,在這個(gè)業(yè)務(wù)系統(tǒng)中大約有 1000 萬(wàn)張表單,且每張表單的字段唯一性規(guī)則可能各不相同,用戶(hù)還能隨意修改這個(gè)規(guī)則。所以,該系統(tǒng)在設(shè)計(jì)實(shí)現(xiàn)時(shí),將所有表單中的所有字段都放到了一張很大的數(shù)據(jù)庫(kù)表中,因此無(wú)法使用數(shù)據(jù)庫(kù)表上的字段唯一性規(guī)則來(lái)處理這個(gè)問(wèn)題。

原來(lái)的 Redis 加鎖實(shí)現(xiàn)方式較為簡(jiǎn)單,且是按照單個(gè)表單來(lái)進(jìn)行加鎖的,所以在單個(gè)表單并發(fā)提交請(qǐng)求吞吐量不是很大的情況下,不會(huì)對(duì)系統(tǒng)性能產(chǎn)生太大影響。

然而,隨著系統(tǒng)業(yè)務(wù)規(guī)模逐漸增大,會(huì)出現(xiàn)少量表單的并發(fā)請(qǐng)求吞吐量暴增的情況。此時(shí),當(dāng)單個(gè)表單提交請(qǐng)求超過(guò)并發(fā)請(qǐng)求吞吐量的上限值后,就會(huì)引發(fā)兩個(gè)較為嚴(yán)重的性能問(wèn)題:

其一,針對(duì)超過(guò)并發(fā)請(qǐng)求吞吐量性能上限值的那個(gè)表單,用戶(hù)在提交表單的頁(yè)面會(huì)出現(xiàn)卡死現(xiàn)象,導(dǎo)致提交數(shù)據(jù)失?。?br>其二,由于后端服務(wù)系統(tǒng)是基于進(jìn)程模型的,而進(jìn)程資源的數(shù)目有限,一旦個(gè)別表單提交數(shù)據(jù)請(qǐng)求的處理進(jìn)程被阻塞,占用大量進(jìn)程資源,就會(huì)導(dǎo)致整個(gè)系統(tǒng)無(wú)法正常處理所有的業(yè)務(wù)請(qǐng)求。

因此,提升單個(gè)表單提交請(qǐng)求吞吐量的性能指標(biāo),就成為了這個(gè)軟件系統(tǒng)性能優(yōu)化的關(guān)鍵問(wèn)題。那么接下來(lái),我們就要先搞明白,這個(gè)互斥鎖是如何影響這個(gè)表單的請(qǐng)求吞吐量性能的。

互斥鎖是如何影響最大請(qǐng)求吞吐量的?

接下來(lái),我就使用一個(gè)公式來(lái)描述下在這個(gè)案例中,使用了 Redis 互斥鎖以后,來(lái)計(jì)算 Max RPS(最大請(qǐng)求吞吐量)的計(jì)算方法,具體公式如下所示:

圖片圖片

在這個(gè)公式中,由于 Lock 和 Unlock 是通過(guò) Redis 的互斥鎖來(lái)實(shí)現(xiàn)的,其使用的 Redis 的 script 腳本實(shí)現(xiàn)如圖所示。經(jīng)在真實(shí)系統(tǒng)中測(cè)量,Lock time 與 Unlock time 的操作時(shí)間之和約為 3ms。接著,可通過(guò)上面的公式進(jìn)行計(jì)算。若中間加鎖的計(jì)算邏輯(resource competition)執(zhí)行開(kāi)銷(xiāo)約為 30ms,那么對(duì)應(yīng)的 Max RPS = 1s / (3ms + 30ms),即大約為 30RPS 左右。也就是說(shuō),只有當(dāng)把加鎖的計(jì)算邏輯降低極限值為 0 時(shí),對(duì)應(yīng)的 Max RPS 才可以達(dá)到 300RPS 左右。這里需要注意的是,因?yàn)闃I(yè)務(wù)中的互斥鎖是全局控制的,所以當(dāng)系統(tǒng)達(dá)到最大 RPS 時(shí),即便通過(guò)彈性擴(kuò)展機(jī)制部署再多的后端服務(wù)實(shí)例進(jìn)程,也無(wú)法再提升這個(gè)性能指標(biāo)了。

至此,在這個(gè)性能優(yōu)化案例中,我們經(jīng)過(guò)測(cè)量得知加鎖的計(jì)算邏輯執(zhí)行時(shí)間為 30RPS,然后根據(jù)上面的公式,計(jì)算出的最大 RPS 值也約為 30RPS 左右,這與真實(shí)的性能測(cè)試獲取的性能指標(biāo)值完全一致。

好的,現(xiàn)在問(wèn)題已經(jīng)比較清楚了。那么,有沒(méi)有辦法可以?xún)?yōu)化提升這個(gè)系統(tǒng)的性能呢?下面我們來(lái)看一下。

性能優(yōu)化解決方案

果這個(gè)業(yè)務(wù)邏輯沒(méi)有增加互斥鎖,在 99.9% 的情況下業(yè)務(wù)邏輯也是正確的。

所以,針對(duì)這種場(chǎng)景,我們可以采用手動(dòng)實(shí)現(xiàn)事務(wù)機(jī)制,優(yōu)化掉業(yè)務(wù)代碼中的互斥鎖,以提升請(qǐng)求吞吐量的性能。

我們已知在這個(gè)案例中,使用互斥鎖解決的核心問(wèn)題是判斷字段不重復(fù)和字段插入操作的原子性問(wèn)題。因此,我們可以考慮采用一些優(yōu)化機(jī)制,單獨(dú)實(shí)現(xiàn)這兩個(gè)操作組合的原子性。

但要注意,如果在互斥鎖的使用場(chǎng)景中,被加鎖的業(yè)務(wù)操作還有更復(fù)雜的一致性要求,比如存在數(shù)據(jù)庫(kù)寫(xiě)沖突的問(wèn)題等,那么這種互斥鎖實(shí)現(xiàn)就不能被簡(jiǎn)單地優(yōu)化掉了。

那么對(duì)于這個(gè)案例中的互斥鎖而言,我們應(yīng)該怎樣優(yōu)化呢?

我來(lái)說(shuō)說(shuō)我想到的優(yōu)化思路。這里呢,為了更清晰地描述該解決方案,我用了一個(gè)流程圖來(lái)給你詳細(xì)地介紹下性能優(yōu)化后的具體實(shí)現(xiàn)過(guò)程,如下圖所示。

圖片圖片

也就是說(shuō),我們可以將 “字段不重復(fù)檢測(cè)”“單個(gè)字段插入”“其他操作” 這三個(gè)操作綁定在一起,實(shí)現(xiàn)一種事務(wù)機(jī)制的能力,以便在后面操作失敗的情況下,能夠回滾到前面的操作中。實(shí)際上,原來(lái)的 Redis 互斥鎖主要是為了實(shí)現(xiàn) “字段不重復(fù)檢測(cè)” 和 “字段的插入操作” 的原子性。而在手動(dòng)實(shí)現(xiàn)事務(wù)機(jī)制之后,我們可以把這兩步操作放到開(kāi)始處執(zhí)行,然后使用 Redis 的 Pipeline 機(jī)制保證這兩步操作組合的原子性,從而不會(huì)被其他 Redis 操作干擾。

這樣,對(duì)于接下來(lái)的其他操作(即用戶(hù)提交數(shù)據(jù)過(guò)程中的一些不可拆分的關(guān)鍵業(yè)務(wù)操作),如果操作成功,就提交任務(wù)成功結(jié)束;如果操作失敗,則需要回滾之前的字段插入操作。另外,為了實(shí)現(xiàn)事務(wù)的機(jī)制和能力,我們還需要在前面字段插入時(shí),同時(shí)記錄插入前的狀態(tài)和插入后的變更狀態(tài),從而實(shí)現(xiàn)失敗后的回滾機(jī)制。

其實(shí),這里我還考慮過(guò)另外兩種實(shí)現(xiàn)方案,分別是基于 Redis 的事務(wù)機(jī)制和基于 MongoDB 上的事務(wù)機(jī)制。但是,我最后在實(shí)現(xiàn)時(shí)并沒(méi)有采納,這背后有很多原因。比如,使用 MongoDB 的事務(wù)需要進(jìn)行數(shù)據(jù)遷移,而且需要升級(jí)系統(tǒng)的 MongoDB 集群的數(shù)據(jù)庫(kù)版本等。以及使用 Redis 事務(wù)機(jī)制的代碼實(shí)現(xiàn)并不友好等等。不過(guò),這里有一個(gè)最重要的原因就是,不管是使用 Redis 事務(wù)還是 MongoDB 上的事務(wù),它們都把對(duì)字段插入操作的沖突時(shí)間,拉長(zhǎng)到了步驟 3 “其他操作” 結(jié)束之后,而這樣就顯著增大了事務(wù)沖突失敗的概率。

所以最后,我們采用前面這種優(yōu)化后的實(shí)現(xiàn)機(jī)制。因?yàn)槿コ嘶コ怄i,所以用戶(hù)間的提交記錄可以更大程度地并行。而且優(yōu)化后的實(shí)現(xiàn)方式,只有 Pipeline 操作會(huì)排隊(duì)處理,而由于單個(gè) Pipeline 的執(zhí)行時(shí)長(zhǎng)在 1ms - 3ms 之間,所以最后優(yōu)化后的表單最大請(qǐng)求吞吐量,就從原來(lái)的 30RPS,提升到了 300RPS 左右,這樣就實(shí)現(xiàn)了性能提升超過(guò) 10 倍的目標(biāo)。

責(zé)任編輯:武曉燕 來(lái)源: 二進(jìn)制跳動(dòng)
相關(guān)推薦

2024-10-29 08:21:05

2021-12-01 11:17:29

Windows 11Windows微軟

2009-11-25 11:28:00

并發(fā)用戶(hù)數(shù)

2018-08-22 09:01:08

2009-11-25 11:32:39

最大用戶(hù)并發(fā)數(shù)系統(tǒng)最大用戶(hù)數(shù)

2023-03-22 13:53:26

芯片英偉達(dá)

2015-01-05 09:56:41

UDPLinux TCP

2022-09-09 09:33:14

支付寶代碼性能

2022-09-27 18:19:32

Java數(shù)據(jù)結(jié)構(gòu)

2022-09-21 17:43:29

Kafka底層網(wǎng)絡(luò)

2012-02-23 13:34:28

2021-01-20 23:40:27

數(shù)據(jù)泄露OpenWRT攻擊

2010-11-04 10:06:27

GSMMTN華為

2024-12-13 13:58:53

2021-02-02 15:38:19

Disruptor緩存Java

2011-03-25 15:21:43

2020-05-19 20:40:09

Windows 10Windows補(bǔ)丁

2021-01-06 10:01:09

數(shù)據(jù)泄露漏洞信息安全

2019-10-08 14:22:43

分布式HDFS算法

2021-03-17 08:11:29

SpringBoot項(xiàng)目數(shù)據(jù)庫(kù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)