秒殺問題其實就是併發讀寫的問題,需要解決超賣,效率等問題。可以使用redis將秒殺的資料進行快取,通過啟用定時任務,當redis中的庫存為0時將,快取持久化到資料庫中,並且將redis中的快取清除掉。
@service
@slf4j
public
class
orderserviceimpl
extends
serviceimpl
implements
orderservice
stock stock1 =
(stock)redisutil.
hget
("stock"
, string.
valueof
(sid));
//校驗庫存
if(stock1.
getcount()
<=0)
//校驗使用者是否已經秒殺過
if(redisutil.
hhaskey
("stockorderlist"
,string.
valueof
(userid)))
//減庫存
int oldversion = stock1.
getversion()
; stock1.
setcount
(stock1.
getcount()
-1);
stock1.
setsale
(stock1.
getsale()
+1);
stock1.
setversion
(oldversion +1)
;//更新redis中的庫存資訊
redisutil.
hset
("stock"
,string.
valueof
(sid)
,stock1)
;//建立訂單
stockorder stockorder =
newstockorder()
; stockorder.
setuserid
(userid)
; stockorder.
setsid
(stock1.
getid()
);stockorder.
setname
(stock1.
getname()
);stockorder.
setcreatetime
(new
date()
);hashmap
ordermap = maps.
newhashmap()
; ordermap.
put(string.
valueof
(stock1.
getid()
),stockorder)
; redisutil.
hset
("stockorderlist"
,string.
valueof
(userid)
,stockorder)
; log.
info
("下單成功");
return apiresult.
success
("下單成功");
}}}
啟用定時任務,當庫存為0時,將秒殺的快取資料持久化到資料庫中。
/**
* 秒殺快取的資料持久化到資料庫中
*/@scheduled
(cron =
"0 0/5 * * * ?"
)public
void
seckilltodb()
);}}
);}}
引入依賴:
<
!-- 訊息佇列 --
>
org.springframework.boot<
/groupid>
spring-boot-starter-amqp<
/artifactid>
org.springframework.boot<
/groupid>
spring-boot-starter-logging<
/artifactid>
<
/exclusion>
<
/exclusions>
<
/dependency>
在springboot的啟動類宣告佇列和交換機
/**
* 宣告佇列
* @return 名為 instantbuy 的訊息佇列
*/@bean
public queue instantbuy()
/** * 宣告交換機
* @return 名為 instantbuyexchange 的交換機
*/@bean
public directexchange instantbuyexchange()
/** * 繫結交換機和佇列
* @return 繫結結果
*/@bean
public binding bind()
定義消費者,監聽訊息佇列:
@component
public
class
instantbuyconsumer
return msg +
"_success";}
}
生產者生產訊息:
@override
public apiresult instantbut
(integer sid, integer userid)
long stockinventory = redisutil.
hnum
("stock"
, string.
valueof
(sid),-
1);if
(stockinventory<0)
//判斷該使用者是否秒殺過該商品,如果秒殺過返回已不能重複秒殺
if(redisutil.
hhaskey
("instantsuccess"
,sid +
","+ userid)
)//該使用者可以正常秒殺
string skillresult =
(string)rabbittemplate.
convertsendandreceive
("instantbuyexchange"
,"instantbuy"
, sid +
","+ userid);if
(stringutils.
isnotblank
(skillresult)
&& skillresult.
equals
(sid +
","+ userid +
"_success"))
else
}}
定時任務:
@scheduled
(cron =
"0 0/1 * * * ?"
)public
void
insertgroups()
}
秒殺專案解決賣超問題
如何保證不賣超 有兩種情況可能會導致賣超 1 乙個使用者同時發出了多個請求,如果庫存足夠,沒加限制,使用者就可以下多個訂單。2 減庫存的sql上沒有加庫存數量的判斷,併發的時候也會導致把庫存減成負數。我們的解決辦法 對於 1 前端加驗證碼,防止使用者同時發出多個請求,在後端的miaosha orde...
關於秒殺和超賣的效能問題
一 秒殺帶來了什麼?秒殺或搶購活動一般會經過 預約 搶訂單 支付 這3個大環節,而其中 搶訂單 這個環節是最考驗業務提供方的抗壓能力的。搶訂單環節一般會帶來2個問題 1 高併發 2 超賣 任何商品都會有數量上限,如何避免成功下訂單買到商品的人數不超過商品數量的上限,這是每個搶購活動都要面臨的難題。二...
秒殺系統防止庫存超賣
第一種 通過資料庫樂觀鎖實現 小型電商 update productstocks set realstock realstock where sku and realstock 0 根據受影響的行數判斷是否執行成功 大型網際網路不是這麼玩的 資料庫有瓶頸 第二種 使用redis 分布式鎖實現 var...