php下用redis解決秒殺超賣問題

2021-09-12 21:48:05 字數 3477 閱讀 2847

秒殺超賣問題,就是有乙個商品搶購活動,乙個商品假如有100件庫存,但是在搶購時有200人來搶購,這時就會併發,原本只有100的庫存但是搶購的人過多,就會發生資料庫裡原本只有100的庫存但是庫存為0的時候還會有人提交成功,這就是超賣。

今天簡單的用redis的佇列來解決超賣問題。因為redis有list型別,list型別其實就是乙個雙向鍊錶。通過push,pop操作從鍊錶的頭部或者尾部新增刪除元素。這使得list既可以用作棧,也可以用作佇列。先進先出  一端進  一端出這就是佇列。這裡用redis就解決了併發的問題,在佇列裡前乙個走完之後,後乙個才會走。

將庫存迴圈lpush進乙個redis值goods_number裡去,然後在下單的時候依次rpop出來。這樣就是下乙個單取出來乙個,然後等goods_number的值為0時,停止下單。

首先建立三個表 store商品表  order訂單表  log日誌表

create table `store` (

`id` int(11) not null auto_increment,

`goods_id` int(11) not null,

`sku_id` int(10) unsigned not null default '0',

`number` int(10) not null default '0',

`freez` float(11,2) not null default '0.00' comment '虛擬庫存',

`price` int(10) not null comment '**:單位為分',

primary key (`id`)

) engine=innodb auto_increment=2 default charset=utf8 comment='庫存';

create table `order` (

`id` int(11) not null auto_increment,

`order_sn` char(32) not null,

`user_id` int(11) not null,

`status` int(11) not null default '0',

`goods_id` int(11) not null default '0',

`sku_id` int(11) not null default '0',

`number` int(11) not null,

`price` int(10) not null comment '**:單位為分',

`create_time` timestamp not null default current_timestamp,

primary key (`id`)

) engine=innodb auto_increment=4743 default charset=utf8 comment='訂單表';

create table `log` (

`id` int(11) not null auto_increment,

`event` varchar(255) not null,

`type` tinyint(4) not null default '0',

`addtime` timestamp not null default current_timestamp,

primary key (`id`)

) engine=myisam auto_increment=10283 default charset=utf8;

測試**如下:

<?php 

namespace home\controller;

use think\cache\driver\redis;

use think\controller;

class testcontroller extends controller

echo $redis->llen('goods_number');

}//生成唯一訂單號

function build_order_no()

//記錄日誌

function insertlog($event,$type=0)

//模擬下單操作

//下單前判斷redis佇列庫存量

function order()

if( ($good_info['number'] - $number) <= 0)

//生成訂單

$order_sn=$this->build_order_no();

$data = array();

$data['order_sn'] = $order_sn;

$data['user_id'] = $user_id;

$data['goods_id'] = $goods_id;

$data['sku_id'] = $sku_id;

$data['number'] = $number;

$data['price'] = $price;

$order_rs=m('order')->add($data);

//庫存減少

$wheres['sku_id'] = $sku_id;

$store_rs=m('store')->where($wheres)->setdec('number',$number);

if($store_rs)else }

}

1、將庫存迴圈存入good_number中   呼叫index方法

2.然後進行併發下單操作。這裡用apache 的ab測試

執行:

在windows系統下,開啟cmd命令列視窗,定位到apache安裝目錄的bin目錄下 f:\wamp\wamp\bin\apache\apache2.4.9\bin

鍵入命令: 

ab -n 800 -c 800   

(-n發出800個請求,-c模擬800併發,請求數要大於或等於併發數。相當800人同時訪問,後面是測試url )

執行成功 檢視表資料

庫存為0,訂單有100個。沒有超賣!

php下用redis解決秒殺超賣問題

秒殺超賣問題,就是有乙個商品搶購活動,乙個商品假如有100件庫存,但是在搶購時有200人來搶購,這時就會併發,原本只有100的庫存但是搶購的人過多,就會發生資料庫裡原本只有100的庫存但是庫存為0的時候還會有人提交成功,這就是超賣。今天簡單的用redis的佇列來解決超賣問題。因為redis有list...

用redis實現秒殺

今日在研究秒殺系統,用資料庫的樂觀鎖可以實現,但是在高併發下可能並不好,所以就想到了快取系統redis,因為redis本身也有鎖機制,廢話不多說,直接上 請大神指點不足的地方。class a public class myrunnable implements runnable override p...

秒殺專案解決賣超問題

如何保證不賣超 有兩種情況可能會導致賣超 1 乙個使用者同時發出了多個請求,如果庫存足夠,沒加限制,使用者就可以下多個訂單。2 減庫存的sql上沒有加庫存數量的判斷,併發的時候也會導致把庫存減成負數。我們的解決辦法 對於 1 前端加驗證碼,防止使用者同時發出多個請求,在後端的miaosha orde...