實現秒殺的幾個想法
第一種場景,秒殺單個商品,多人搶佔一個商品資源,可以使用唯一索引進行控制.
commodity是商品表,記錄可以秒殺的商品
commodity_log是秒殺記錄表,記錄那些使用者成功秒殺了哪些商品
實驗初始化了五個商品(id為1,2,3,4,5),並且在秒殺記錄表建立了一個唯一索引
假設20號使用者秒殺1號商品,大致過程如下
start transaction;
insert into commodity_log(commodityId,userid) values(1,20);
rollback;
這種方式的優點是實現簡單,缺點是在併發環境下,有阻塞.
第二種場景,秒殺的每種商品,有不同的剩餘數量.
commodity表的Quantity欄位,表示本次秒殺的商品總數
commodity_log表的state欄位,表示是否秒殺成功,0表示不成功,1表示成功.
主要邏輯如下
select if(count(*)<
(select max(quantity) from commodity a where a.commodityId=commodityId),true,false) into flag
from commodity_log where commodityId=v_commodityId;
這段進行一個基本判斷,如果秒殺記錄表的記錄已經超過了本次秒殺的商品數量,則直接退出.
如果沒有超過本次的秒殺商品數量,則記錄一個秒殺日誌
在併發的環境下,因為沒有加鎖的併發控制,插入的日誌記錄一定大於商品數量
所以按照commodity_log日誌表的自增ID作為行為先後的判斷依據.
如果秒殺成功,則回寫狀態.
這種方式沒有鎖和阻塞.但是sql語句大幅增加
秒殺不成功有兩種場景.第一種會有一個select語句,第二種兩個select語句和一個insert語句
秒殺成功,兩個select語句,一個insert語句和一個update語句。
這種方案雖然避免了秒殺中使用鎖和阻塞,但是增加了很多sql語句.
哪種更好呢?
我也不太清楚.
後記:
最佳化版
過程中移除了commit,轉到程式中控制.
參考:
http://jiagou.baijia.baidu.com/article/108134?qq-pf-to=pcqq.group
/>
commodity是商品表,記錄可以秒殺的商品
commodity_log是秒殺記錄表,記錄那些使用者成功秒殺了哪些商品
實驗初始化了五個商品(id為1,2,3,4,5),並且在秒殺記錄表建立了一個唯一索引
-
drop table commodity;
-
drop table commodity_log;
-
create table commodity (commodityId int,userid int);
-
create table commodity_log (id int primary key auto_increment,commodityId int,userid int);
-
insert into commodity(commodityId) values(1),(2),(3),(4),(5);
- create unique index inx_1 on commodity_log(commodityId);
假設20號使用者秒殺1號商品,大致過程如下
start transaction;
insert into commodity_log(commodityId,userid) values(1,20);
如果沒有異常
update commodity set userid=20 where commodityId=1;
commit;
如果有異常,表示秒殺失敗update commodity set userid=20 where commodityId=1;
commit;
rollback;
這種方式的優點是實現簡單,缺點是在併發環境下,有阻塞.
第二種場景,秒殺的每種商品,有不同的剩餘數量.
commodity表的Quantity欄位,表示本次秒殺的商品總數
commodity_log表的state欄位,表示是否秒殺成功,0表示不成功,1表示成功.
-
drop table commodity;
-
drop table commodity_log;
-
create table commodity (commodityId int,Quantity int);
-
create table commodity_log (id int primary key auto_increment,commodityId int,userid int,state int default 0);
- insert into commodity(commodityId,Quantity) values(1,5),(2,5),(3,3),(4,1),(5,2);
主要邏輯如下
-
drop procedure buy;
-
-
delimiter $$
-
create procedure buy(v_commodityId int,v_userid int,out result varchar(20))
-
begin
-
declare flag int;
-
declare v_log_id int;
-
-
start transaction;
-
select if(count(*)<
-
(select max(quantity) from commodity a where a.commodityId=commodityId),true,false) into flag
-
from commodity_log where commodityId=v_commodityId;
-
if flag=true then
-
insert into commodity_log(commodityId,userid) values(v_commodityId,v_userid);
-
select id into v_log_id from (
-
select id,userid,@a:=@a+1 rn from commodity_log,(select @a:=0) t where commodityId=v_commodityId order by id
-
) a where rn <=(select max(quantity) from commodity a where a.commodityId=v_commodityId) and userid=v_userid;
-
if v_log_id is not null then
-
update commodity_log set state=1 where id=v_log_id;
-
set result='成功秒殺';
-
else
-
set result='秒殺失敗';
-
end if;
-
else
-
set result='秒殺失敗';
-
end if;
-
commit;
-
end $$
- delimiter ;
(select max(quantity) from commodity a where a.commodityId=commodityId),true,false) into flag
from commodity_log where commodityId=v_commodityId;
這段進行一個基本判斷,如果秒殺記錄表的記錄已經超過了本次秒殺的商品數量,則直接退出.
如果沒有超過本次的秒殺商品數量,則記錄一個秒殺日誌
在併發的環境下,因為沒有加鎖的併發控制,插入的日誌記錄一定大於商品數量
所以按照commodity_log日誌表的自增ID作為行為先後的判斷依據.
如果秒殺成功,則回寫狀態.
這種方式沒有鎖和阻塞.但是sql語句大幅增加
秒殺不成功有兩種場景.第一種會有一個select語句,第二種兩個select語句和一個insert語句
秒殺成功,兩個select語句,一個insert語句和一個update語句。
這種方案雖然避免了秒殺中使用鎖和阻塞,但是增加了很多sql語句.
哪種更好呢?
我也不太清楚.
後記:
最佳化版
-
drop procedure buy;
-
-
delimiter $$
-
create procedure buy(v_commodityId int,v_userid int,out result varchar(20))
-
begin
-
declare flag int;
-
declare v_log_id int;
-
declare v_quantity int;
-
declare v_id int;
-
-
start transaction;
-
select quantity into v_quantity from commodity a where a.commodityId = v_commodityId;
-
-
select if(count(*)<v_quantity,true,false) into flag
-
from commodity_log where commodityId=v_commodityId;
-
-
if flag=true then
-
insert into commodity_log(commodityId,userid) values(v_commodityId,v_userid);
-
SELECT LAST_INSERT_ID() into v_id;
-
-
select id into v_log_id from (
-
select id,@a:=@a+1 rn from commodity_log,(select @a:=0) t where commodityId=v_commodityId order by id
-
) a where rn <=v_quantity and id=v_id;
-
-
if v_log_id is not null then
-
update commodity_log set state=1 where id=v_log_id;
-
set result='成功秒殺';
-
else
-
set result='秒殺失敗';
-
end if;
-
else
-
set result='秒殺失敗';
-
end if;
-
end $$
- delimiter ;
參考:
http://jiagou.baijia.baidu.com/article/108134?qq-pf-to=pcqq.group
/>
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/29254281/viewspace-1783043/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 同步秒殺實現:Redis在秒殺功能的實踐Redis
- 從京東618秒殺聊聊秒殺限流的多種實現
- RocketMQ實現優惠券秒殺MQ
- 秒殺最佳化-基於阻塞佇列實現秒殺最佳化佇列
- Redis輕鬆實現秒殺系統Redis
- 呼叫幾個介面,快速實現社交遊戲“劇本殺”遊戲
- 基於redis分散式鎖實現“秒殺”Redis分散式
- 用Redis輕鬆實現秒殺系統Redis
- 用 Redis 輕鬆實現秒殺系統Redis
- 【Redis核心知識】實現秒殺的三種方案Redis
- 一個想法,不知能否實現。
- 秒殺架構實踐架構
- Redis在秒殺功能的實踐Redis
- 雲端計算秒殺電商秒殺
- Redis 實現高併發下的搶購 / 秒殺功能Redis
- js程式碼實現倒數計時秒殺的效果JS
- 秒殺系統:如何打造並維護一個超大流量的秒殺系統?
- Android 實現GridView的橫向滾動,實現仿京東秒殺效果AndroidView
- 單機秒殺系統的架構設計與實現架構
- python版:單機redis實現秒殺,防止超限PythonRedis
- 使用redis watch實現秒殺搶購,避免超賣Redis
- 關於搶購秒殺的實現思路與事例程式碼
- 大型PHP電商網站商品秒殺功能實現思路分析PHP網站
- 高併發秒殺系統架構詳解,不是所有的秒殺都是秒殺!架構
- 秒殺系統設計的5個要點
- 如何設計一個秒殺系統
- 如何設計一個秒殺系統?
- 短影片直播系統,實現高併發秒殺的多種方式
- SSM框架實現高併發秒殺API學習筆記SSM框架API筆記
- Redis秒殺實戰-微信搶紅包-秒殺庫存,附案例原始碼(Jmeter壓測)Redis原始碼JMeter
- 秒殺流程圖流程圖
- 【高併發】秒殺系統架構解密,不是所有的秒殺都是秒殺(升級版)!!架構解密
- 如何設計一個優秀的秒殺系統?
- 經驗:一個秒殺系統的設計思考
- 在CGI中實現session的想法和實現 (轉)Session
- 北京驚現“秒殺Google的辦公室” 這是真的嗎?Go
- 怎麼設計一個秒殺系統
- 擁有一個永遠無法實現的想法的樂趣