秒殺功能(6)RabbitMQ

2021-09-22 10:00:05 字數 4192 閱讀 6381

這篇講解的內容較多。先解決業務問題再解決效能問題。

之前的**中有兩類業務問題:

超賣;若乙個使用者用兩個平台同時秒殺某一商品,可能會出現該使用者秒殺兩件商品的情況。

這兩個問題雖然業務問題很大,但**改動特別小。

//改動前的**

@update

("update miaosha_goods set stock_count = stock_count - 1 where goods_id = #"

)public int reducestock

(miaoshagoods g)

;//改動後的**

@update

("update miaosha_goods set stock_count = stock_count - 1 where goods_id = # and stock_count > 0"

)public int reducestock

(miaoshagoods g)

;//利用資料庫的鎖來保證不會賣超(資料庫本身會保證不會有兩個執行緒同時改一條記錄)

@service

public

class

orderservice

@transactional

public orderinfo createorder

(miaoshauser user, goodsvo goods)

}

可以看到,**中就改動了兩點,一是查詢重複訂單時是在快取中查,第二點是,在資料庫中建立秒殺訂單和訂單詳情後,會在快取中插入使用者id和商品id結合的鍵(值是秒殺訂單),為之後在快取中查詢做準備。

秒殺系統的效能瓶頸一般是在對資料庫的訪問上,若能減少對資料的訪問,就能在很大程度上提高併發量。

大致的思路是:

redis預減庫存減少資料庫的訪問;

記憶體標記減少redis訪問;

請求先入隊緩衝,非同步下單,增強使用者體驗。

具體的**流程是:

系統初始化,把商品庫存數量載入到redis中;

收到請求,先在記憶體標記上判斷商品是否秒殺完畢,若沒有,則進入下一步;

redis預減庫存,庫存不足,直接返回,否則進入下一步;

redis中判斷是否重複下單,若沒有進入下一步;

請求入隊,前端頁面立即返回排隊中;

請求出隊,資料庫中判斷庫存、快取中判斷是否重複秒殺,若都成功進入下一步;

資料庫中減少庫存,資料庫中生成訂單,在快取中生成使用者和商品的鍵以便之後驗證是否重複下單;

客戶端輪詢(前端中實現),是否秒殺成功。

controller層

在這部分主要完成:

系統的初始化,把秒殺商品的庫存數量載入到redis中;

記憶體中判斷商品是否秒殺完、redis預減庫存、判斷是否重複秒殺、入隊操作。

@controller

("/miaosha"

)public

class

miaoshacontroller

implements

initializingbean

for(goodsvo goods : goodslist)

}//第三版,訊息佇列的方式

;//從token中讀使用者資訊

//記憶體標記,減少redis訪問

boolean over = localovermap.

get(goodsid);if

(over)

//預減庫存

long stock = redisservice.

decr

(goodskey.getmiaoshagoodsstock,

""+ goodsid);if

(stock <0)

//判斷是否已經秒殺到了

miaoshaorder order = orderservice.

getmiaoshaorderbyuseridgoodsid

(user.

getid()

, goodsid);if

(order !=

null

)//入隊

miaoshamessage mm =

newmiaoshamessage()

; mm.

setuser

(user)

; mm.

setgoodsid

(goodsid)

; sender.

sendmiaoshamessage

(mm)

;return result.

success(0

);//排隊中

}}

其中,miaoshamessage的定義為:

public

class

miaoshamessage

rabbitmq相關操作

@service

public

class

mqsender

}

@service

public

class

mqreceiver

//判斷是否已經秒殺到了

miaoshaorder order = orderservice.

getmiaoshaorderbyuseridgoodsid

(user.

getid()

, goodsid);if

(order !=

null

)//減庫存 下訂單 寫入秒殺訂單

miaoshaservice.

miaosha

(user, goods);}

}

其中,miaoshaservice.miaosha(user, goods)操作為:

@service

public

class

miaoshaservice

else

}}

目前,優化完成了。當使用者請求到達controller層,在到達資料庫之前,記憶體map和redis會抵擋大部分的資料庫訪問操作,大概只有與秒殺商品個數差不多的請求會進入佇列從而訪問資料庫。

在之前寫的秒殺功能(3)的壓測中,初步版本的tps = 808/sec;

本次的壓測結果為:

tps = 908/sec,略高一些,沒有提高太多,這可能是和硬體條件有關,我的伺服器效能不高。

資料庫情況

(這篇寫完我是奔潰的,,明明在幾個小時前我就能寫完。。中間開了個組會我掉網了。。我還沒儲存。。於是寫了兩遍。。又拖累了今天的進度,offer君又遠離我一步。。 )

秒殺介面優化 rabbitMq 配置

本篇部落格rabbitmq 的配置安裝是在虛擬機器下centos 6.5 版本中完成,從rabbitmq服務的啟動到客戶端的訪問,確實走了不少坑,這裡詳細說明 0.秒殺優化瓶頸 減少資料庫的訪問 1.系統初始化,把商品庫存數量載入到redis 2.收到請求,redis 預減少庫存,庫存不足,直接返回...

商城秒殺功能實現

令牌機制實現秒殺功能 利用定時任務 或資料庫作業 將某些商品在規定時間之後要開啟秒殺,根據庫存量同步到快取 redis 中。根據每乙個商品產生對應的token數量,1.redis快取採用 中的list資料型別儲存每個商品的令牌。採用list資料型別儲存的原因主要是每乙個執行緒從list中pop時是單...

flask redis實現搶購(秒殺)功能

今天面試了 一家非常高大上的公司,問了我關於redis的實用性問題,但是答的不是很好,所以下午通過再次學習 redis,實現相關實用性功能的一種。對於搶購功能,難點在於 搶購時 由於高併發請求,導致乙個使用者搶購多件商品,庫存量小於訂單量的情況。如下通過redis的hash和list型別實現相關功能...