高并發一直是網站上線後會遇到的一個嚴峻的考驗,渡過了一切都好,渡不過就是當機。
在電商時代如此發達的今天,高并發無此不在雙十一 、618、雙十二,還有雷猴王的某米手機搶購。首先我們要分析高并發究竟會給我們開發者帶來什麼樣的挑戰
大量的請求,如果僅僅隻有一台伺服器肯定是吃不消的,通常一些公司都是一台伺服器上部署了很多個網站也充當了資料庫伺服器、redis伺服器。如果要應用高并發沒有足夠的硬體支援是不行的。我們需要進行 分布式叢集 以及 負載均衡
硬體支援有了過後,我們就需要下一步的分析
這時我們還需要提高網站的吞吐量,怎麼提高呢?首先我們需要針對io密集型做異步化操作,搶單的頁面不隻是有搶單按鈕,還有商品的介紹,圖檔,文字描述等。對于這些資料我們要進行緩存,一萬個使用者一萬次請求都從資料庫中取資料與隻取一次剩下9999次從緩存中取效率自然是不一樣的
上面說的都是為了解決一個 高 字,而并發才是我們真正需要準備的,假如兩個使用者同時請求,這時庫存還有1,程式裡先判斷庫存是不是1,現在都符合條件,然後進行生成訂單等操作。就發生了資源共享的問題,明明隻有一個訂單,但是兩個使用者都完成了訂單,那麼這個商品應該給誰呢?
并發
假設的邏輯,我們使用者進行了請求,我們把他們的資訊放到庫裡,但是隻有前十個人是可以購買商品的,因為庫存隻有10個
也許我們可以用鎖來解決并發的問題,但是鎖無疑帶來的是效率的低下,使用者體驗也極低。我們想要的是快速傳回,但是後面那一堆的邏輯怎麼辦呢?我們可以使用rabbitmq隊列,使用者的請求到達了搶單接口,我們隻向隊列中丢一條資料後就立即傳回
這時又來了一個問題,會有同一個使用者多次進行請求的情況,如果像之前的邏輯,前10條資訊有二條是屬于一個人的呢,(這裡假設每個人隻可以購買一次)我們就需要進行判斷了,同一個賬戶發送的多次請求,我們隻認為第一次請求是有效的,剩下的都請都直接傳回。因為是并發,我們又怎麼做到第一次請求有效呢?這時我們可以使用redis incr存儲使用者的辨別,redis是單線程的,不存在并發的問題。incr傳回為1那麼是第一次請求,為n則是第n請求那麼它就是無效的。這是請求辨別
請求辨別我們可以在搶單接口就進行判斷,也就是先拿使用者的辨別去incr,傳回為1則丢到隊列,不為1則不丢到隊列。 也可以在rabbitmq的消費端進行處理,從rabbitmq消息隊列中拿到使用者資訊後,進行incr。再進行下一步操作
丢到了消息隊列中,我們還需要去處理,consumer我們肯定是要有多個的,我們可以使用平分分發與手動傳遞。在這裡我們把使用者的資訊進行入庫,當然入庫後我們再向redis中存入一條入庫辨別
上面都是在後端,用戶端這裡點選了搶單按鈕後可以立即導向排隊界面(是不是很熟悉,某米。。。)在這個界面進行輪詢五秒一次,判斷目前使用者在庫中的位置,如果是前十,那麼就進行訂單操作,不是。。。那就再等,看看會不會有其他使用者放棄購買資格。
其實講到這裡,已經差不多了,成功的把并行變成了串行。剩下的就是業務處理,怎麼做都可以。其實對于并發還可以有其它的處理方式,比如樂觀鎖也可以有效的控制并發,可以看我的相關文章,其中就有關于樂觀鎖的實作
源碼下載下傳位址 http://pan.baidu.com/s/1pkfzyyj 密碼 mf50