redis實戰 高併發搶購案例

2021-10-07 14:14:36 字數 2554 閱讀 6822

先普及一下,什麼叫超賣,訂單商品資料量大於商品庫存數量,就叫做超賣;

那麼問題來了,為什麼會超賣呢?

在**搶購中,假如庫存為100個,這時有100 000個併發請求過來了,最後庫存只剩1個時,假如還有1000個併發請求,如果這1000個請求都成功了,那最後庫存是不是變成了-999,這就是超賣。(以上僅為理論上理解超賣)

先介紹乙個很有用的工具,併發測試工具ab.exe,在apache的bin目錄下開啟cmd視窗,輸入命令ab -n10000 -c1000 http://localhost/code/mysql.php

,表示測試10000個請求,併發量為1000,測試訪問位址為http://localhost/code/mysql.php

先建乙個商品表,store為庫存,以下為一些用到sql語句

// 建表

create table product(

id int(8) not null auto_increment comment '產品id',

name varchar(25) not null default '' comment '產品名',

price decimal(10,3) not null default 0 comment '**',

store int(8) not null default 0 comment '庫存',

primary key(id)

)engine=innodb default charset=utf8;

// 新增資料

insert into product value(1, '小公尺手環', 198, 10);

// 檢視表資料

select * from product;

// 設定庫存

update product set store=10 where id=1;

接下來,用**解釋下高併發搶購的超賣,直接在mysql上測試,以下就是mysql.php檔案

<?php 

header("content-type:text/html; charset=utf-8");

// 連線資料庫

$pdo = new pdo('mysql:host=localhost;dbname=test', 'root', 'root') or die("資料庫連線失敗");

$pdo->exec("set names utf8");

$sql = "select * from product where id=1";

$res = $pdo->query($sql);

$data = $res->fetch(pdo::fetch_assoc);

// print_r($data);

if($data['store']>0)else

$pdo->commit();

}else

?>

給它10000個請求,併發為1000

來看下商品表中的庫存store

再來看下用redis實現的,用到了redis的事務、樂觀鎖,以下為redis.php

<?php 

header("content-type:text/html; charset=utf-8");

// 連線資料庫

$pdo = new pdo('mysql:host=localhost;dbname=test', 'root', 'root') or die("資料庫連線失敗");

$pdo->exec("set names utf8");

$redis = new redis();

$redis->connect("localhost");

$redis->watch('salec'); // 虛擬銷量

$salec = $redis->get('salec');

$store = 10; // 設定虛擬庫存與資料庫的一致

if($salec >= $store)

// 開啟事務

$redis->multi();

$redis->incr('salec'); // 增加銷量

$res = $redis->exec(); // 執行事務 如果發現自己拿到的key被修改了,事務則被打斷

if($res)

}else

?>

也給它10000個請求,併發為1000

看下商品表中的庫存store

redis完美解決了高併發搶購的超賣現象。

高併發下搶購

了解高併發以及怎麼處理後,測試一下專案中下單的 邏輯很簡單,goods表中stock設定為unsigned。剛開始你可能會覺得這樣會出現超單的情況,但是測試後,沒有出現超單的情況。看似沒有問題,但是看過日誌發現問題還挺多的。這之前請看下這篇文章裡面有處理高併發下單的情況。goods id num g...

java基於redis實現高併發 搶購例項

面試常常遇到寫乙個搶購例項,或者講講搶購實現想法,然後總是講不明白,因為目前工作沒做搶購這一塊兒。但是這個想法今天終於搞明白了,其中也參照了一些大佬的做法。junit測試類 log log logfactory.getlog getclass autowired private redistempl...

redis實現高併發下的搶購 秒殺功能

常規寫法 查詢出對應商品的庫存,看是否大於0,然後執行生成訂單等操作,但是在判斷庫存是否大於0處,如果在高併發下就會有問題,導致庫存量出現負數 redis的解決方案 1,inlcude oncea include db.php redis new redis resid connect 127.0....