.Net高並發解決思路


轉自:

本文如有不對之處,歡迎各位拍磚扶正。另源碼在文章最下面,大家下載過后先還原一下nuget包,需要改一下redis的配置,rabbitmq的配置以及Ef的連接字符串。另外使用的是CodeFirst,先update-database生成數據庫后再進行操作

高並發

高並發一直是網站上線后會遇到的一個嚴峻的考驗,渡過了一切都好,渡不過就是宕機。

在電商時代如此發達的今天,高並發無此不在雙十一 、618、雙十二,還有雷猴王的某米手機搶購。首先我們要分析高並發究竟會給我們開發者帶來什么樣的挑戰

大量的請求,如果僅僅只有一台服務器肯定是吃不消的,通常一些公司都是一台服務器上部署了很多個網站也充當了數據庫服務器、redis服務器。如果要應用高並發沒有足夠的硬件支持是不行的。我們需要進行 分布式集群 以及 負載均衡

硬件支持有了過后,我們就需要下一步的分析

這時我們還需要提高網站的吞吐量,怎么提高呢?首先我們需要針對IO密集型異步化操作,搶單的頁面不只是有搶單按鈕,還有商品的介紹,圖片,文字描述等。對於這些數據我們要進行緩存,一萬個用戶一萬次請求都從數據庫中取數據與只取一次剩下9999次從緩存中取效率自然是不一樣的

上面說的都是為了解決一個  字,而並發才是我們真正需要准備的,假如兩個用戶同時請求,這時庫存還有1,程序里先判斷庫存是不是1,現在都符合條件,然后進行生成訂單等操作。就發生了資源共享的問題,明明只有一個訂單,但是兩個用戶都完成了訂單,那么這個商品應該給誰呢?

並發

假設現在是一個電商網站,今天要舉辦活動,有10個商品低價銷售,但是會來搶購的人會特別多,最后只有十個人可以成功的買到商品

假設的邏輯,我們用戶進行了請求,我們把他們的信息放到庫里,但是只有前十個人是可以購買商品的,因為庫存只有10個

也許我們可以用鎖來解決並發的問題,但是鎖無疑帶來的是效率的低下,用戶體驗也極低。我們想要的是快速返回,但是后面那一堆的邏輯怎么辦呢?我們可以使用RabbitMq隊列,用戶的請求到達了搶單接口,我們只向隊列中丟一條數據后就立即返回

這時又來了一個問題,會有同一個用戶多次進行請求的情況,如果像之前的邏輯,前10條信息有二條是屬於一個人的呢,(這里假設每個人只可以購買一次)我們就需要進行判斷了,同一個賬戶發送的多次請求,我們只認為第一次請求是有效的,剩下的都請都直接返回。因為是並發,我們又怎么做到第一次請求有效呢?這時我們可以使用Redis incr存儲用戶的標識,Redis是單線程的,不存在並發的問題。incr返回為1那么是第一次請求,為N則是第N請求那么它就是無效的。這是請求標識

請求標識我們可以在搶單接口就進行判斷,也就是先拿用戶的標識去Incr,返回為1則丟到隊列,不為1則不丟到隊列。

也可以在rabbitmq的消費端進行處理,從rabbitmq消息隊列中拿到用戶信息后,進行incr。再進行下一步操作

丟到了消息隊列中,我們還需要去處理,consumer我們肯定是要有多個的,我們可以使用平分分發手動交付。在這里我們把用戶的信息進行入庫,當然入庫后我們再向Redis中存入一條入庫標識

上面都是在后端,客戶端這里點擊了搶單按鈕后可以立即導向排隊界面(是不是很熟悉,某米。。。)在這個界面進行輪詢五秒一次,判斷當前用戶在庫中的位置,如果是前十,那么就進行訂單操作,不是。。。那就再等,看看會不會有其他用戶放棄購買資格。

其實講到這里,已經差不多了,成功的把並行變成了串行。剩下的就是業務處理,怎么做都可以。其實對於並發還可以有其它的處理方式,比如樂觀鎖也可以有效的控制並發,可以看我的相關文章,其中就有關於樂觀鎖的實現


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM