日本黄色一级经典视频|伊人久久精品视频|亚洲黄色色周成人视频九九九|av免费网址黄色小短片|黄色Av无码亚洲成年人|亚洲1区2区3区无码|真人黄片免费观看|无码一级小说欧美日免费三级|日韩中文字幕91在线看|精品久久久无码中文字幕边打电话

當前位置:首頁 > > 架構(gòu)師社區(qū)
[導讀]秒殺系統(tǒng)相信很多人見過,比如京東或者淘寶的秒殺,小米手機的秒殺,那么秒殺系統(tǒng)的后臺是如何實現(xiàn)的呢?


-     前言     -


秒殺系統(tǒng)相信很多人見過,比如京東或者淘寶的秒殺,小米手機的秒殺,那么秒殺系統(tǒng)的后臺是如何實現(xiàn)的呢?我們?nèi)绾卧O計一個秒殺系統(tǒng)呢?對于秒殺系統(tǒng)應該考慮哪些問題?如何設計出健壯的秒殺系統(tǒng)?本文我們就來探討一下這個問題。


雙十一秒殺架構(gòu)模型設計實踐!

-     秒殺應該考慮哪些問題     -

1、超賣問題 分析秒殺的業(yè)務場景,最重要的有一點就是超賣問題,假如備貨只有 100 個,但是最終超賣了 200,一般來講秒殺系統(tǒng)的價格都比較低,如果超賣將嚴重影響公司的財產(chǎn)利益,因此首當其沖的就是解決商品的超賣問題。
2、高并發(fā) 秒殺具有時間短、并發(fā)量大的特點,秒殺持續(xù)時間只有幾分鐘,而一般公司都為了制造轟動效應,會以極低的價格來吸引用戶,因此參與搶購的用戶會非常的多。短時間內(nèi)會有大量請求涌進來,后端如何防止并發(fā)過高造成緩存擊穿或者失效,擊垮數(shù)據(jù)庫都是需要考慮的問題。
3、接口防刷 現(xiàn)在的秒殺大多都會出來針對秒殺對應的軟件,這類軟件會模擬不斷向后臺服務器發(fā)起請求,一秒幾百次都是很常見的,如何防止這類軟件的重復無效請求,防止不斷發(fā)起的請求也是需要我們針對性考慮的。
4、秒殺 url 對于普通用戶來講,看到的只是一個比較簡單的秒殺頁面,在未達到規(guī)定時間,秒殺按鈕是灰色的,一旦到達規(guī)定時間,灰色按鈕變成可點擊狀態(tài)。這部分是針對小白用戶的,如果是稍微有點電腦功底的用戶,會通過 F12 看瀏覽器的 network 看到秒殺的 url,通過特定軟件去請求也可以實現(xiàn)秒殺。或者提前知道秒殺 url 的人,一請求就直接實現(xiàn)秒殺了。這個問題我們需要考慮解決。
5、數(shù)據(jù)庫設計 秒殺有把我們服務器擊垮的風險,如果讓它與我們的其他業(yè)務使用在同一個數(shù)據(jù)庫中,耦合在一起,就很有可能牽連和影響其他的業(yè)務。如何防止這類問題發(fā)生,就算秒殺發(fā)生了宕機、服務器卡死問題,也應該讓他盡量不影響線上正常進行的業(yè)務。
6、大量請求問題 按照「高并發(fā)」的考慮,就算使用緩存還是不足以應對短時間的高并發(fā)的流量的沖擊。如何承載這樣巨大的訪問量,同時提供穩(wěn)定低時延的服務保證,是需要面對的一大挑戰(zhàn)。我們來算一筆賬,假如使用的是 Redis 緩存,單臺 Redis 服務器可承受的 QPS 大概是 4W 左右,如果一個秒殺吸引的用戶量足夠多的話,單 QPS 可能達到幾十萬,單體 Redis 還是不足以支撐如此巨大的請求量。緩存會被擊穿,直接滲透到 DB,從而擊垮 MySQL,后臺會將會大量報錯。

-     秒殺系統(tǒng)的設計和技術方案     -

1、秒殺系統(tǒng)數(shù)據(jù)庫設計 針對「數(shù)據(jù)庫設計」提出的秒殺數(shù)據(jù)庫的問題,因此應該單獨設計一個秒殺數(shù)據(jù)庫,防止因為秒殺活動的高并發(fā)訪問拖垮整個網(wǎng)站。這里只需要兩張表,一張是秒殺訂單表,一張是秒殺貨品表。


雙十一秒殺架構(gòu)模型設計實踐!

雙十一秒殺架構(gòu)模型設計實踐!


其實應該還有幾張表,商品表:可以關聯(lián) goods_id 查到具體的商品信息,商品圖像、名稱、平時價格、秒殺價格等,還有用戶表:根據(jù)用戶 user_id 可以查詢到用戶昵稱、用戶手機號,收貨地址等其他額外信息,這個具體就不給出實例了。
2、秒殺 url 的設計 為了避免有程序訪問經(jīng)驗的人通過下單頁面url直接訪問后臺接口來秒殺貨品,我們需要將秒殺的 url 實現(xiàn)動態(tài)化,即使是開發(fā)整個系統(tǒng)的人都無法在秒殺開始前知道秒殺的 url。具體的做法就是通過md5加密一串隨機字符作為秒殺的 url,然后前端訪問后臺獲取具體的 url,后臺校驗通過之后才可以繼續(xù)秒殺。
3、秒殺頁面靜態(tài)化 將商品的描述、參數(shù)、成交記錄、圖像、評價等全部寫入到一個靜態(tài)頁面,用戶請求不需要通過訪問后端服務器,不需要經(jīng)過數(shù)據(jù)庫,直接在前臺客戶端生成,這樣可以最大可能的減少服務器的壓力。具體的方法可以使用 freemarker 模板技術,建立網(wǎng)頁模板,填充數(shù)據(jù),然后渲染網(wǎng)頁。
4、單體 Redis 升級為集群 Redis 秒殺是一個讀多寫少的場景,使用Redis做緩存再合適不過。不過考慮到緩存擊穿問題,我們應該構(gòu)建 Redis 集群,采用哨兵模式,可以提升 Redis 的性能和可用性。
5、使用 Nginx Nginx 是一個高性能 Web 服務器,它的并發(fā)能力可以達到幾萬,而 Tomcat 只有幾百。通過 Nginx 映射客戶端請求,再分發(fā)到后臺 Tomcat 服務器集群中可以大大提升并發(fā)能力。
6、精簡SQL 典型的一個場景是在進行扣減庫存的時候,傳統(tǒng)的做法是先查詢庫存,再去 update。這樣的話需要兩個 SQL,而實際上一個 SQL 我們就可以完成的??梢杂眠@樣的做法:update miaosha_goods set stock =stock-1 where goos_id ={#goods_id} and version = #{version} and sock>0;這樣的話,就可以保證庫存不會超賣并且一次更新庫存,還有注意一點這里使用了版本號的樂觀鎖,相比較悲觀鎖,它的性能較好。
7、Redis 預減庫存 很多請求進來,都需要后臺查詢庫存,這是一個頻繁讀的場景??梢允褂?Redis 來預減庫存,在秒殺開始前可以在 Redis 設值,比如 redis.set(goodsId,100),這里預放的庫存為 100 可以設值為常量,每次下單成功之后,Integer stock = (Integer)redis.get(goosId); 然后判斷 sock 的值,如果小于常量值就減去 1;不過注意當取消的時候,需要增加庫存,增加庫存的時候也得注意不能大于之間設定的總庫存數(shù)(查詢庫存和扣減庫存需要原子操作,此時可以借助lua腳本)下次下單再獲取庫存的時候,直接從 Redis 里面查就可以了。
8、接口限流 秒殺最終的本質(zhì)是數(shù)據(jù)庫的更新,但是有很多大量無效的請求,我們最終要做的就是如何把這些無效的請求過濾掉,防止?jié)B透到數(shù)據(jù)庫。限流的話,需要入手的方面很多:
(1)前端限流 首先第一步就是通過前端限流,用戶在秒殺按鈕點擊以后發(fā)起請求,那么在接下來的5秒是無法點擊(通過設置按鈕為 disable)。這一小舉措開發(fā)起來成本很小,但是很有效。
(2)同一個用戶 xx 秒內(nèi)重復請求直接拒絕 具體多少秒需要根據(jù)實際業(yè)務和秒殺的人數(shù)而定,一般限定為 10 秒。具體的做法就是通過 Redis 的鍵過期策略,首先對每個請求都從 String value = redis.get(userId);如果獲取到這個 value 為空或者為 null,表示它是有效的請求,然后放行這個請求。如果不為空表示它是重復性請求,直接丟掉這個請求。如果有效,采用 redis.setexpire(userId,value,10).value 可以是任意值,一般放業(yè)務屬性比較好,這個是設置以 userId 為 key,10 秒的過期時間(10秒后,key對應的值自動為null)。
(3)令牌桶算法限流 接口限流的策略有很多,我們這里采用令牌桶算法。令牌桶算法的基本思路是每個請求嘗試獲取一個令牌,后端只處理持有令牌的請求,生產(chǎn)令牌的速度和效率我們都可以自己限定,Guava 提供了 RateLimter 的 API 供我們使用。以下做一個簡單的例子,注意需要引入 Guava:

		
		
public class TestRateLimiter {

    public static void main(String[] args) {
        //1秒產(chǎn)生1個令牌
        final RateLimiter rateLimiter = RateLimiter.create(1); for (int i = 0; i < 10; i++) { //該方法會阻塞線程,直到令牌桶中能取到令牌為止才繼續(xù)向下執(zhí)行。 double waitTime= rateLimiter.acquire(); System.out.println("任務執(zhí)行" + i + "等待時間" + waitTime);
        }
        System.out.println("執(zhí)行結(jié)束");
    }
}


上面代碼的思路就是通過 RateLimiter 來限定我們的令牌桶每秒產(chǎn)生 1 個令牌(生產(chǎn)的效率比較低),循環(huán) 10 次去執(zhí)行任務。acquire 會阻塞當前線程直到獲取到令牌,也就是如果任務沒有獲取到令牌,會一直等待。那么請求就會卡在我們限定的時間內(nèi)才可以繼續(xù)往下走,這個方法返回的是線程具體等待的時間。執(zhí)行如下:


雙十一秒殺架構(gòu)模型設計實踐!


可以看到任務執(zhí)行的過程中,第1個是無需等待的,因為已經(jīng)在開始的第 1 秒生產(chǎn)出了令牌。接下來的任務請求就必須等到令牌桶產(chǎn)生了令牌才可以繼續(xù)往下執(zhí)行。如果沒有獲取到就會阻塞(有一個停頓的過程)。不過這個方式不太好,因為用戶如果在客戶端請求,如果較多的話,直接后臺在生產(chǎn) token 就會卡頓(用戶體驗較差),它是不會拋棄任務的,我們需要一個更優(yōu)秀的策略:如果超過某個時間沒有獲取到,直接拒絕該任務。接下來再來個案例:

public class TestRateLimiter2 {

    public static void main(String[] args) {
        final RateLimiter rateLimiter = RateLimiter.create(1); for (int i = 0; i < 10; i++) { long timeOut = (long) 0.5; boolean isValid = rateLimiter.tryAcquire(timeOut, TimeUnit.SECONDS); System.out.println("任務" + i + "執(zhí)行是否有效:" + isValid); if (!isValid) { continue;
            }
            System.out.println("任務" + i + "在執(zhí)行");
        }
        System.out.println("結(jié)束");
    }
}

其中用到了 tryAcquire 方法,這個方法的主要作用是設定一個超時的時間,如果在指定的時間內(nèi)預估(注意是預估并不會真實的等待),如果能拿到令牌就返回 true,如果拿不到就返回 false。然后我們讓無效的直接跳過,這里設定每秒生產(chǎn)1個令牌,讓每個任務嘗試在 0.5 秒獲取令牌,如果獲取不到,就直接跳過這個任務(放在秒殺環(huán)境里就是直接拋棄這個請求)。程序?qū)嶋H運行如下:


雙十一秒殺架構(gòu)模型設計實踐!


只有第 1 個獲取到了令牌,順利執(zhí)行了,下面的基本都直接拋棄了,因為 0.5 秒內(nèi),令牌桶(1秒1個)來不及生產(chǎn)就肯定獲取不到返回false了。
這個限流策略的效率有多高呢?假如我們的并發(fā)請求是 400 萬瞬間的請求,將令牌產(chǎn)生的效率設為每秒 20 個,每次嘗試獲取令牌的時間是 0.05 秒,那么最終測試下來的結(jié)果是,每次只會放行 4 個左右的請求,大量的請求會被拒絕,這就是令牌桶算法的優(yōu)秀之處。
9、異步下單 為了提升下單的效率,并且防止下單服務的失敗。需要將下單這一操作進行異步處理。最常采用的辦法是使用隊列,隊列最顯著的三個優(yōu)點:異步、削峰、解耦。這里可以采用 RabbitMQ,在后臺經(jīng)過了限流、庫存校驗之后,流入到這一步驟的就是有效請求。然后發(fā)送到隊列里,隊列接受消息,異步下單。下完單,入庫沒有問題可以用短信通知用戶秒殺成功。假如失敗的話,可以采用補償機制,重試。
10、服務降級 假如在秒殺過程中出現(xiàn)了某個服務器宕機,或者服務不可用,應該做好后備工作。之前的博客里有介紹通過 Hystrix 進行服務熔斷和降級,可以開發(fā)一個備用服務,假如服務器真的宕機了,直接給用戶一個友好的提示返回,而不是直接卡死,服務器錯誤等生硬的反饋。

-     總結(jié)     -

秒殺流程圖:


雙十一秒殺架構(gòu)模型設計實踐!


這就是我設計出來的秒殺流程圖,當然不同的秒殺體量針對的技術選型都不一樣,這個流程可以支撐起幾十萬的流量,如果是成千萬破億那就得重新設計了。
比如數(shù)據(jù)庫的分庫分表、隊列改成用 Kafka、Redis 增加集群數(shù)量等手段。通過本次設計主要是要表明的是我們?nèi)绾螒獙Ω卟l(fā)的處理,并開始嘗試解決它,在工作中多思考、多動手能提升我們的能力水平,加油!如果本篇博客有任何錯誤,請麻煩指出來,不勝感激。



免責聲明:本文內(nèi)容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯(lián)系我們,謝謝!

本站聲明: 本文章由作者或相關機構(gòu)授權發(fā)布,目的在于傳遞更多信息,并不代表本站贊同其觀點,本站亦不保證或承諾內(nèi)容真實性等。需要轉(zhuǎn)載請聯(lián)系該專欄作者,如若文章內(nèi)容侵犯您的權益,請及時聯(lián)系本站刪除。
換一批
延伸閱讀

LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: 驅(qū)動電源

在工業(yè)自動化蓬勃發(fā)展的當下,工業(yè)電機作為核心動力設備,其驅(qū)動電源的性能直接關系到整個系統(tǒng)的穩(wěn)定性和可靠性。其中,反電動勢抑制與過流保護是驅(qū)動電源設計中至關重要的兩個環(huán)節(jié),集成化方案的設計成為提升電機驅(qū)動性能的關鍵。

關鍵字: 工業(yè)電機 驅(qū)動電源

LED 驅(qū)動電源作為 LED 照明系統(tǒng)的 “心臟”,其穩(wěn)定性直接決定了整個照明設備的使用壽命。然而,在實際應用中,LED 驅(qū)動電源易損壞的問題卻十分常見,不僅增加了維護成本,還影響了用戶體驗。要解決這一問題,需從設計、生...

關鍵字: 驅(qū)動電源 照明系統(tǒng) 散熱

根據(jù)LED驅(qū)動電源的公式,電感內(nèi)電流波動大小和電感值成反比,輸出紋波和輸出電容值成反比。所以加大電感值和輸出電容值可以減小紋波。

關鍵字: LED 設計 驅(qū)動電源

電動汽車(EV)作為新能源汽車的重要代表,正逐漸成為全球汽車產(chǎn)業(yè)的重要發(fā)展方向。電動汽車的核心技術之一是電機驅(qū)動控制系統(tǒng),而絕緣柵雙極型晶體管(IGBT)作為電機驅(qū)動系統(tǒng)中的關鍵元件,其性能直接影響到電動汽車的動力性能和...

關鍵字: 電動汽車 新能源 驅(qū)動電源

在現(xiàn)代城市建設中,街道及停車場照明作為基礎設施的重要組成部分,其質(zhì)量和效率直接關系到城市的公共安全、居民生活質(zhì)量和能源利用效率。隨著科技的進步,高亮度白光發(fā)光二極管(LED)因其獨特的優(yōu)勢逐漸取代傳統(tǒng)光源,成為大功率區(qū)域...

關鍵字: 發(fā)光二極管 驅(qū)動電源 LED

LED通用照明設計工程師會遇到許多挑戰(zhàn),如功率密度、功率因數(shù)校正(PFC)、空間受限和可靠性等。

關鍵字: LED 驅(qū)動電源 功率因數(shù)校正

在LED照明技術日益普及的今天,LED驅(qū)動電源的電磁干擾(EMI)問題成為了一個不可忽視的挑戰(zhàn)。電磁干擾不僅會影響LED燈具的正常工作,還可能對周圍電子設備造成不利影響,甚至引發(fā)系統(tǒng)故障。因此,采取有效的硬件措施來解決L...

關鍵字: LED照明技術 電磁干擾 驅(qū)動電源

開關電源具有效率高的特性,而且開關電源的變壓器體積比串聯(lián)穩(wěn)壓型電源的要小得多,電源電路比較整潔,整機重量也有所下降,所以,現(xiàn)在的LED驅(qū)動電源

關鍵字: LED 驅(qū)動電源 開關電源

LED驅(qū)動電源是把電源供應轉(zhuǎn)換為特定的電壓電流以驅(qū)動LED發(fā)光的電壓轉(zhuǎn)換器,通常情況下:LED驅(qū)動電源的輸入包括高壓工頻交流(即市電)、低壓直流、高壓直流、低壓高頻交流(如電子變壓器的輸出)等。

關鍵字: LED 隧道燈 驅(qū)動電源
關閉