1. 程式人生 > >使用Mysql和Redis設計搶購邏輯

使用Mysql和Redis設計搶購邏輯

spa 速度 fetch count pre 業務 如果 charset con

搶購場景中,要保證兩點:

1.庫存不會超減/少賣

2.在1基礎上的執行速度

我測試了兩種方案,

方案一.Mysql開啟事務

我把庫存表簡單設計如下

CREATE TABLE `la_store` (
  `id` int(11) NOT NULL,
  `val` int(255) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

假設庫存有100000件(val=100000)

php邏輯代碼

<?php
$stime=microtime(true);
$count=100000;//測試次數
while($count>0){
$count-=1; $con = mysql_connect("localhost","user","pwd"); if (!$con) { die(‘Could not connect: ‘ . mysql_error()); } mysql_select_db("database_name", $con); mysql_query(‘begin‘); $record=mysql_query("select * from la_store where id = 1 for update");//獲取獨占鎖 $record=mysql_fetch_array($record); if
($record[‘val‘]>0){//判斷是否還有庫存 //有庫存的邏輯 $res=mysql_query("UPDATE la_test SET val = val-1 WHERE id=1 ");//更新庫存 }else{
//沒庫存的邏輯
}
mysql_query("commit"); mysql_close($con); } $etime=microtime(true);//獲取程序執行結束的時間 $total=$etime-$stime; echo $total;

方案二.使用Redis開啟事務

假設庫存有100000件(set store 100000)

<?php
$stime=microtime(true
);//開始時間 $count=100000;//測試次數 while($count>0){ $count-=1; $redis = new Redis(); $redis->connect(‘127.0.0.1‘, 6379); $res=$redis->multi()->decr(‘store‘)->get(‘store‘)->exec(); if($res[1]>0){ //有庫存邏輯 }else{ //沒有庫存邏輯 } } $etime=microtime(true);//獲取程序執行結束的時間 print_r($res); $total=$etime-$stime; echo $total;

測試結果:

分別執行,經過100000次循環後,Redis用時22秒,Mysql用時50秒;

使用Redis更快,但Redis的事務不能回滾,如果業務邏輯出錯時允許不回滾,並且回滾的概率很小,建議使用Redis.如果邏輯出錯時必須回滾,還是用Mysql更穩妥.

使用Mysql和Redis設計搶購邏輯