mq 非同步寫mysql MQ非同步下單簡單流程分析

2021-10-20 01:34:13 字數 2550 閱讀 7047

秒殺專案非同步下單的流程一:

瀏覽器傳送請求,首先請求到服務時,會先執行引數校驗,如果校驗失敗直接返回給前端,如果校驗成功則執行下單方法

​ 其中的校驗方法主要是利用redis的快取機制,即所有參加校驗的資料都存入redis中,因為這些是熱點資料,需要頻繁訪問,利用vo的校驗,和庫存的校驗就需要存入redis中,首先就是redis要在專案開始的時候進行初始化,為了是將所有的使用者存入redis中,這樣不用頻繁訪問資料庫獲取使用者資訊,還有將將獲取所有的秒殺商品物件即volist結合,然後遍歷volist集合,將每個vo轉為json字串存入redis中(需要定義redis的key,這裡的redis使用hash的資料結構進行儲存,避免key值太多,造成hash衝突),然後獲取每個vo物件中的庫存資訊,然後同樣定義乙個key存入redis中,(由於使用的是hash結構儲存,那麼最外層的key就是乙個標識,表示存的是庫存還是秒殺商品,裡層的key用秒殺商品id儲存,value就是存vo物件或庫存),

​ 這樣初始化redis之後,所有的熱點資料都存入redis中了,校驗時,比如校驗秒殺商品是否存在,需要根據頁面傳的秒殺商品id去redis中查詢有沒有對應的商品資訊,如果有,需要判斷這個商品是否在活動範圍之內(用時間進行判斷),需要判斷使用者是否已經下過單(使用redis的setnx指令對應的**,表示沒有就存,有就不存),最後判斷庫存是否足夠(使用redis去快取中查使用increment機制,進行原子性遞增(-1)),當校驗成功後,需要下單,這時候就要利用rocketmq傳送非同步下單,到訊息中介軟體上,無論後面的消費者執行下單成功與否,訊息中介軟體都會響應給瀏覽器,可以響應正在排隊中,或其他,,,,

當將訊息傳送到訊息中介軟體上以後,會與namesever建立長連線,然後將訊息存入到中介軟體的bucket中,bucket中有乙個topic專門存入一些主題訊息,乙個topic中可以存入4個sequence訊息佇列,然後消費者也就是需要下單的業務會訂閱這個訊息中介軟體,消費者其實就是乙個***,用來監聽訊息中介軟體上的訊息,然後從上面獲取訊息,獲取指定tag的訊息,也就是乙個物件(這個物件封裝了下單需要的秒殺商品id和使用者id),然後消費者獲取這兩個id,然後呼叫下單的方法,將這兩個引數傳進入然後獲取下單id,但是並不能保證下單一定成功,需要進行try-catch

​ 然後在try裡面要傳送下單成功的訊息到訊息中介軟體中(目的是需要告訴瀏覽器剛才的請求是否傳送成功),將獲取的下單id和uuid(uuid是從前端頁面傳過來的id)封裝成乙個物件作為傳送rocketmq非同步請求的訊息傳送至訊息中心

​ 訊息中心獲取到這個訊息以後會存入到bucket中.這時候為了讓瀏覽器可以隨時獲取傳送請求之後響應這裡使用乙個與瀏覽器進行長連線的乙個協議即為:websocket協議,因此需要新建乙個websocket服務作為與瀏覽器進行長連線的乙個服務,(前端會傳送乙個請求與websocket建立長連線)它既是消費者也是生產者,它會作為消費者從訊息中心上將秒殺成功或者失敗的訊息獲取下來,然後獲取訊息中的引數:uuid(非常重要),下單id 然後通過websocketserver的clients將uuid作為引數獲取指定的客戶端,也就是所謂的session.如果session不為空,則建立乙個result物件,將下單成功的訊息物件封裝進入result物件中,然後通過session.getbasicremote().senttext()方法將result物件傳進去,即可以給瀏覽器傳送請求,且這個連線是長連線,主要是通過uuid獲取哪個使用者的傳送的請求,然後通過websocket找到這使用者然後將相應給他,這就是mq非同步下單的大致流程.....

rocketmq非同步下單流程二:

主要是針對建立訂單失敗和成功的情況,當秒殺服務中建立訂單的***在接收到註冊中心中的訊息以後,需要去執行建立訂單的業務,(扣減庫存,建立基礎訂單 和秒殺訂單)同時也會傳送訊息到註冊中心,告知訊息中心秒殺成功,如果建立訂單失敗,還用還要在catch中往訊息中心傳送秒殺失敗的訊息,(同時需要redis庫存回補,清除使用者下單標記和本地標記)

​ 如果秒殺成功,即下單成功,還需要在傳送乙個延遲訊息到訊息中心(用來檢查訂單是夠超時未支付)

​ 秒殺服務中新建立乙個訂單成功後延遲訊息的***(主要用來監聽訂單是否超時未支付),如果監聽到訊息,則表示訂單需要支付的時間已過期,這時,需要判斷訂單是否已支付(通過查詢訂單),如果已支付則不用做任何操作,如果未支付,需要將訂單的支付狀態改為超時未支付狀態,同時還需要進行mysql資料庫中的庫存回補,然後將庫存同步到redis庫存中,還用清除本地標記(比如:當前庫存為0時,由於可能秒殺伺服器有多個,只清除本次的這台伺服器有可能造成庫存回補了,其他使用者在其他伺服器上進行下單時會顯示庫存不足,這就是由於本地標識存在,沒有清除,導致庫存不足)因此為了能夠清除所有伺服器的本地標識,使用訊息中介軟體的廣播訊息這個機制去傳送訊息,這樣所有的伺服器都會收到清除本地標識的訊息,這樣建立乙個清除本地 標識的***進行監聽,當收到訊息時,則呼叫controller去清除本地標識(將map快取中的true改為false)

當秒殺服務建立訂單失敗後,有建立訂單的***根據建立訂單失敗的異常資訊作為訊息傳送到訊息中心中,這時候需要在websocket服務中建立乙個秒殺失敗的***,專門用來監聽失敗訊息,如果監聽到訊息,則會將訊息中的異常資訊封裝進result物件中,然後根據uuid找到對應的客戶端,然後通過session.getbassicremote.senttext()將result傳到前端頁面,使用者就可以知道下單失敗了

非同步Socket寫聊天程式

socket 網路應用程式如同一般檔案 i o一樣在資料訪問未完成的時候,整個應用程式會停滯,直到網路操作完全成功為止。若是遇上不佳的網路環境,這種情形將會嚴重影響整個網路程式的運作。對於網路延遲,net 提供了自己的一組解決方法,非同步操作。socket 類提供的方法成員中包含一組專門用來進行非同...

走進非同步程式設計的世界 剖析非同步方法(下)

本文 自 感謝大家的支援,這是昨天發布 走進非同步程式設計的世界 剖析非同步方法 上 的補充篇。await 表示式也可以使用 try.catch.finally 結構。internal class program 任務狀態 console.writeline 任務完成狀態標識 console.wri...

非同步 佇列寫日誌檔案

using system using system.collections.generic using system.io using system.linq using system.text using system.threading.tasks namespace sysloginfo 寫入...