熟女丰满少妇精品一区二区,国产精品第一页综合在线,亚洲人成色777777精品,午夜性色福利免费视频在线播放

<object id="t794i"><abbr id="t794i"><center id="t794i"></center></abbr></object>

    <small id="t794i"><u id="t794i"></u></small>
    <address id="t794i"></address>
    <small id="t794i"><kbd id="t794i"></kbd></small>

      1. 甘肅信息港

        小米手機越來越容易搶的背后:搶購系統(tǒng)的優(yōu)化!

        分享到:
         2021-02-19 07:09:18 來源: 閱讀:-G0

        我和同事們對小米網(wǎng)的搶購系統(tǒng)做了最后的檢查與演練。幾個小時后,小米網(wǎng)今年開年來最重要的一次大型活動“米粉節(jié)”就要開始了。

        這次米粉節(jié)活動,是小米電商的成人禮,是一次重要的考試。小米網(wǎng)從網(wǎng)站前端、后臺系統(tǒng)、倉儲物流、售后等各個環(huán)節(jié),都將接受一次全面的壓力測試。

        10點整,一波流量高峰即將到來,幾百萬用戶將準點擠入小米網(wǎng)的服務器。而首先迎接壓力沖擊的,就是擋在最前面的搶購系統(tǒng)。

        小米手機越來越容易搶的背后:搶購系統(tǒng)的優(yōu)化


        而這個搶購系統(tǒng)是重新開發(fā)、剛剛上線不久的,這是它第一次接受這樣嚴峻的考驗。

        系統(tǒng)能不能頂住壓力?能不能順暢正確地執(zhí)行業(yè)務邏輯?這些問題不到搶購高峰那一刻,誰都不能百分百確定。

        9點50分,流量已經(jīng)爬升得很高了;10點整,搶購系統(tǒng)自動開啟,購物車中已經(jīng)順利加入了搶購商品。

        一兩分鐘后,熱門的搶購商品已經(jīng)售罄自動停止搶購。搶購系統(tǒng)抗住了壓力。

        我長舒一口氣,之前積累的壓力都消散了。我坐到角落的沙發(fā)里,默默回想搶購系統(tǒng)所經(jīng)歷的那些驚心動魄的故事。這可真是一場很少人有機會經(jīng)歷的探險呢。

        搶購系統(tǒng)是怎樣誕生的

        時間回到2011年底。小米公司在這一年8月16日首次發(fā)布了手機,立刻引起了市場轟動。隨后,在一天多的時間內(nèi)預約了30萬臺。之后的幾個月,這30萬臺小米手機通過排號的方式依次發(fā)貨,到當年年底全部發(fā)完。

        然后便是開放購買。最初的開放購買直接在小米的商城系統(tǒng)上進行,但我們那時候完全低估了“搶購”的威力。瞬間爆發(fā)的平常幾十倍流量迅速淹沒了小米網(wǎng)商城服務器,數(shù)據(jù)庫死鎖、網(wǎng)頁刷新超時,用戶購買體驗非常差。

        市場需求不等人,一周后又要進行下一輪開放搶購。一場風暴就等在前方,而我們只有一周的時間了,整個開發(fā)部都承擔著巨大的壓力。

        小米網(wǎng)可以采用的常規(guī)優(yōu)化手段并不太多,增加帶寬、服務器、尋找代碼中的瓶頸點優(yōu)化代碼。但是,小米公司只是一家剛剛成立一年多的小公司,沒有那么多的服務器和帶寬。而且,如果代碼中有瓶頸點,即使能增加一兩倍的服務器和帶寬,也一樣會被瞬間爆發(fā)的幾十倍負載所沖垮。而要優(yōu)化商城的代碼,時間上已沒有可能。電商網(wǎng)站很復雜,說不定某個不起眼的次要功能,在高負載情況下就會成為瓶頸點拖垮整個網(wǎng)站。

        這時開發(fā)組面臨一個選擇,是繼續(xù)在現(xiàn)有商城上優(yōu)化,還是單獨搞一套搶購系統(tǒng)?我們決定冒險一試,我和幾個同事一起突擊開發(fā)一套獨立的搶購系統(tǒng),希望能夠絕境逢生。

        擺在我們面前的是一道似乎無解的難題,它要達到的目標如下:

        • 只有一周時間,一周內(nèi)完成設計、開發(fā)、測試、上線;
        • 失敗的代價無法承受,系統(tǒng)必須順暢運行;
        • 搶購結果必須可靠;
        • 面對海量用戶的并發(fā)搶購,商品不能賣超;
        • 一個用戶只能搶一臺手機;
        • 用戶體驗盡量好些。


        設計方案就是多個限制條件下求得的解。時間、可靠性、成本,這是我們面臨的限制條件。要在那么短的時間內(nèi)解決難題,必須選擇最簡單可靠的技術,必須是經(jīng)過足夠驗證的技術,解決方案必須是最簡單的。

        在高并發(fā)情況下,影響系統(tǒng)性能的一個關鍵因素是:數(shù)據(jù)的一致性要求。在前面所列的目標中,有兩項是關于數(shù)據(jù)一致性的:商品剩余數(shù)量、用戶是否已經(jīng)搶購成功。如果要保證嚴格的數(shù)據(jù)一致性,那么在集群中需要一個中心服務器來存儲和操作這個值。這會造成性能的單點瓶頸。

        在分布式系統(tǒng)設計中,有一個CAP原理?!耙恢滦?、可用性、分區(qū)容忍性”三個要素最多只能同時實現(xiàn)兩點,不可能三者兼顧。我們要面對極端的爆發(fā)流量負載,分區(qū)容忍性和可用性會非常重要,因此決定犧牲數(shù)據(jù)的強一致性要求。

        做出這個重要的決定后,剩下的設計決定就自然而然地產(chǎn)生了:

        1. 技術上要選擇最可靠的,因為團隊用PHP的居多,所以系統(tǒng)使用PHP開發(fā);
        2. 搶資格過程要最簡化,用戶只需點一個搶購按鈕,返回結果表示搶購成功或者已經(jīng)售罄;
        3. 對搶購請求的處理盡量簡化,將I/O操作控制到最少,減少每個請求的時間;
        4. 盡量去除性能單點,將壓力分散,整體性能可以線性擴展;
        5. 放棄數(shù)據(jù)強一致性要求,通過異步的方式處理數(shù)據(jù)。


        最后的系統(tǒng)原理見后面的第一版搶購系統(tǒng)原理圖(圖1)。


        小米手機越來越容易搶的背后:搶購系統(tǒng)的優(yōu)化



        圖1 第一版搶購系統(tǒng)原理圖


        系統(tǒng)基本原理:在PHP服務器上,通過一個文件來表示商品是否售罄。如果文件存在即表示已經(jīng)售罄。PHP程序接收用戶搶購請求后,查看用戶是否預約以及是否搶購過,然后檢查售罄標志文件是否存在。對預約用戶,如果未售罄并且用戶未搶購成功過,即返回搶購成功的結果,并記錄一條日志。日志通過異步的方式傳輸?shù)街行目刂乒?jié)點,完成記數(shù)等操作。

        最后,搶購成功用戶的列表異步導入商場系統(tǒng),搶購成功的用戶在接下來的幾個小時內(nèi)下單即可。這樣,流量高峰完全被搶購系統(tǒng)擋住,商城系統(tǒng)不需要面對高流量。

        在這個分布式系統(tǒng)的設計中,對持久化數(shù)據(jù)的處理是影響性能的重要因素。我們沒有選擇傳統(tǒng)關系型數(shù)據(jù)庫,而是選用了Redis服務器。選用Redis基于下面幾個理由。

        1. 首先需要保存的數(shù)據(jù)是典型的Key/Value對形式,每個UID對應一個字符串數(shù)據(jù)。傳統(tǒng)數(shù)據(jù)庫的復雜功能用不上,用KV庫正合適。
        2. Redis的數(shù)據(jù)是in-memory的,可以極大提高查詢效率。
        3. Redis具有足夠用的主從復制機制,以及靈活設定的持久化操作配置。這兩點正好是我們需要的。


        在整個系統(tǒng)中,最頻繁的I/O操作,就是PHP對Redis的讀寫操作。如果處理不好,Redis服務器將成為系統(tǒng)的性能瓶頸。

        系統(tǒng)中對Redis的操作包含三種類型的操作:查詢是否有預約、是否搶購成功、寫入搶購成功狀態(tài)。為了提升整體的處理能力,可采用讀寫分離方式。

        所有的讀操作通過從庫完成,所有的寫操作只通過控制端一個進程寫入主庫。

        在PHP對Redis服務器的讀操作中,需要注意的是連接數(shù)的影響。如果PHP是通過短連接訪問Redis服務器的,則在高峰時有可能堵塞Redis服務器,造成雪崩效應。這一問題可以通過增加Redis從庫的數(shù)量來解決。

        而對于Redis的寫操作,在我們的系統(tǒng)中并沒有壓力。因為系統(tǒng)是通過異步方式,收集PHP產(chǎn)生的日志,由一個管理端的進程來順序寫入Redis主庫。

        另一個需要注意的點是Redis的持久化配置。用戶的預約信息全部存儲在Redis的進程內(nèi)存中,它向磁盤保存一次,就會造成一次等待。嚴重的話會導致?lián)屬徃叻鍟r系統(tǒng)前端無法響應。因此要盡量避免持久化操作。我們的做法是,所有用于讀取的從庫完全關閉持久化,一個用于備份的從庫打開持久化配置。同時使用日志作為應急恢復的保險措施。

        整個系統(tǒng)使用了大約30臺服務器,其中包括20臺PHP服務器,以及10臺Redis服務器。在接下來的搶購中,它順利地抗住了壓力?;叵肫甬敃r的場景,真是非常的驚心動魄。

        小米手機越來越容易搶的背后:搶購系統(tǒng)的優(yōu)化


        第二版搶購系統(tǒng)

        經(jīng)過了兩年多的發(fā)展,小米網(wǎng)已經(jīng)越來越成熟。公司準備在2014年4月舉辦一次盛大的“米粉節(jié)”活動。這次持續(xù)一整天的購物狂歡節(jié)是小米網(wǎng)電商的一次成人禮。商城前端、庫存、物流、售后等環(huán)節(jié)都將經(jīng)歷一次考驗。

        對于搶購系統(tǒng)來說,最大的不同就是一天要經(jīng)歷多輪搶購沖擊,而且有多種不同商品參與搶購。我們之前的搶購系統(tǒng),是按照一周一次搶購來設計及優(yōu)化的,根本無法支撐米粉節(jié)復雜的活動。而且經(jīng)過一年多的修修補補,第一版搶購系統(tǒng)積累了很多的問題,正好趁此機會對它進行徹底重構。

        第二版系統(tǒng)主要關注系統(tǒng)的靈活性與可運營性(圖2)。對于高并發(fā)的負載能力,穩(wěn)定性、準確性這些要求,已經(jīng)是基礎性的最低要求了。我希望將這個系統(tǒng)做得可靈活配置,支持各種商品各種條件組合,并且為將來的擴展打下良好的基礎。


        小米手機越來越容易搶的背后:搶購系統(tǒng)的優(yōu)化



        圖2 第二版系統(tǒng)總體結構圖


        在這一版中,搶購系統(tǒng)與商城系統(tǒng)依然隔離,兩個系統(tǒng)之間通過約定的數(shù)據(jù)結構交互,信息傳遞精簡。通過搶購系統(tǒng)確定一個用戶搶得購買資格后,用戶自動在商城系統(tǒng)中將商品加入購物車。

        在之前第一版搶購系統(tǒng)中,我們后來使用Go語言開發(fā)了部分模塊,積累了一定的經(jīng)驗。因此第二版系統(tǒng)的核心部分,我們決定使用Go語言進行開發(fā)。

        我們可以讓Go程序常駐內(nèi)存運行,各種配置以及狀態(tài)信息都可以保存在內(nèi)存中,減少I/O操作開銷。對于商品數(shù)量信息,可以在進程內(nèi)進行操作。不同商品可以分別保存到不同的服務器的Go進程中,以此來分散壓力,提升處理速度。

        系統(tǒng)服務端主要分為兩層架構,即HTTP服務層和業(yè)務處理層。HTTP服務層用于維持用戶的訪問請求,業(yè)務處理層則用于進行具體的邏輯判斷。兩層之間的數(shù)據(jù)交互通過消息隊列來實現(xiàn)。

        HTTP服務層主要功能如下:

        1. 進行基本的URL正確性校驗;
        2. 對惡意訪問的用戶進行過濾,攔截黃牛;
        3. 提供用戶驗證碼;
        4. 將正常訪問用戶數(shù)據(jù)放入相應商品隊列中;
        5. 等待業(yè)務處理層返回的處理結果。


        業(yè)務處理層主要功能如下:

        1. 接收商品隊列中的數(shù)據(jù);
        2. 對用戶請求進行處理;
        3. 將請求結果放入相應的返回隊列中。


        用戶的搶購請求通過消息隊列,依次進入業(yè)務處理層的Go進程里,然后順序地處理請求,將搶購結果返回給前面的HTTP服務層。

        商品剩余數(shù)量等信息,根據(jù)商品編號分別保存在業(yè)務層特定的服務器進程中。我們選擇保證商品數(shù)據(jù)的一致性,放棄了數(shù)據(jù)的分區(qū)容忍性。

        這兩個模塊用于搶購過程中的請求處理,系統(tǒng)中還有相應的策略控制模塊,以及防刷和系統(tǒng)管理模塊等(圖3)。


        小米手機越來越容易搶的背后:搶購系統(tǒng)的優(yōu)化



        圖3 第二版系統(tǒng)詳細結構圖


        在第二版搶購系統(tǒng)的開發(fā)過程中,我們遇到了HTTP層Go程序內(nèi)存消耗過多的問題。

        由于HTTP層主要用于維持住用戶的訪問請求,每個請求中的數(shù)據(jù)都會占用一定的內(nèi)存空間,當大量的用戶進行訪問時就會導致內(nèi)存使用量不斷上漲。當內(nèi)存占用量達到一定程度(50%)時,Go中的GC機制會越來越慢,但仍然會有大量的用戶進行訪問,導致出現(xiàn)“雪崩”效應,內(nèi)存不斷上漲,最終機器內(nèi)存的使用率會達到90%以上甚至99%,導致服務不可用。

        在Go語言原生的HTTP包中會為每個請求分配8KB的內(nèi)存,用于讀緩存和寫緩存。而在我們的服務場景中只有GET請求,服務需要的信息都包含在HTTP Header中,并沒有Body,實際上不需要如此大的內(nèi)存進行存儲。

        為了避免讀寫緩存的頻繁申請和銷毀,HTTP包建立了一個緩存池,但其長度只有4,因此在大量連接創(chuàng)建時,會大量申請內(nèi)存,創(chuàng)建新對象。而當大量連接釋放時,又會導致很多對象內(nèi)存無法回收到緩存池,增加了GC的壓力。

        HTTP協(xié)議是構建在TCP協(xié)議之上的,Go的原生HTTP模塊中是沒有提供直接的接口關閉底層TCP連接的,而HTTP 1.1中對連接狀態(tài)默認使用keep-alive方式。這樣,在客戶端多次請求服務端時,可以復用一個TCP連接,避免頻繁建立和斷開連接,導致服務端一直等待讀取下一個請求而不釋放連接。但同樣在我們的服務場景中不存在TCP連接復用的需求。當一個用戶完成一個請求后,希望能夠盡快關閉連接。keep-alive方式導致已完成處理的用戶連接不能盡快關閉,連接無法釋放,導致連接數(shù)不斷增加,對服務端的內(nèi)存和帶寬都有影響。

        通過上面的分析,我們的解決辦法如下。

        1. 在無法優(yōu)化Go語言中GC機制時,要避免“雪崩效應”就要盡量避免服務占用的內(nèi)存超過限制(50%),在處于這個限制內(nèi)時,GC可以有效進行??赏ㄟ^增加服務器的方式來分散內(nèi)存壓力,并盡力優(yōu)化服務占用的內(nèi)存大小。同時Go 1.3也對其GC做了一定優(yōu)化。
        2. 我們?yōu)閾屬忂@個特定服務場景定制了新的HTTP包,將TCP連接讀緩存大小改為1KB。
        3. 在定制的HTTP包中,將緩存池的大小改為100萬,避免讀寫緩存的頻繁申請和銷毀。
        4. 當每個請求處理完成后,通過設置Response的Header中Connection為close來主動關閉連接。


        通過這樣的改進,我們的HTTP前端服務器最大穩(wěn)定連接數(shù)可以超過一百萬。

        第二版搶購系統(tǒng)順利完成了米粉節(jié)的考驗。

        小米手機越來越容易搶的背后:搶購系統(tǒng)的優(yōu)化


        總結

        技術方案需要依托具體的問題而存在。脫離了應用場景,無論多么酷炫的技術都失去了價值。搶購系統(tǒng)面臨的現(xiàn)實問題復雜多變,我們也依然在不斷地摸索改進。

        簡歷又被刷了,應屆程序員簡歷就該這么寫

        了解常用緩存淘汰算法,這就夠了

        推薦閱讀:only汽車網(wǎng)

        文章評價COMMENT

        還可以輸入2000個字

        暫無網(wǎng)友的評論

        意見反饋

        ×
        J