PHP Redis解決高併發下的秒殺(樂觀鎖思路)

2021-09-17 22:12:09 字數 2366 閱讀 3897

搶購、秒殺是平常很常見的場景,面試的時候面試官也經常會問到,比如問你**中的搶購秒殺是怎麼實現的等等。

搶購、秒殺實現很簡單,但是有些問題需要解決,主要針對兩個問題:

一、高併發對資料庫產生的壓力

二、競爭狀態下如何解決庫存的正確減少("超賣"問題)

第乙個問題,對於php來說很簡單,用快取技術就可以緩解資料庫壓力,比如memcache,redis等快取技術。

第二個問題就比較複雜點:

常規寫法:

查詢出對應商品的庫存,看是否大於0,然後執行生成訂單等操作,但是在判斷庫存是否大於0處,如果在高併發下就會有問題,導致庫存量出現負數(超賣)。

例如(1)a購買商品,查詢庫存為1,可以購買

(2)減少庫存,提交訂單

(1)和(2)之間執行是有時間的,這中間b也來購買這個商品,他查詢出的庫存也是1,之後提交訂單,庫存就會變為-1

例如(1)a購買商品,查詢庫存為1,可以購買

(2)b購買商品,查詢庫存為1,可以購買(出現髒讀)

(3)a提交訂單,減少庫存,庫存減至0

(4)b提交訂單,減少庫存,庫存減至-1

<?php

$conn

=mysql_connect

("localhost"

,"root"

,"root");

if(!$conn

)mysql_select_db

("test"

,$conn);

$price=10

;$user_id=1

;$goods_id=1

;$sku_id=11

;$number=1

;//生成唯一訂單號

function

build_order_no()

//記錄日誌

function

add_num_log

($event

,$type=0

)//模擬下單操作

//庫存是否大於0

$sql

="select number from ih_store where goods_id='$goods_id

' and sku_id='$sku_id'";

$rs=

mysql_query

($sql

,$conn);

$row

=mysql_fetch_assoc

($rs);

if($row

['number'

]>0)

where sku_id='$sku_id'";

$store_rs

=mysql_query

($sql

,$conn);

if(mysql_affected_rows()

)else

}else

下面是redis的樂觀鎖思路

例如(1)a購買商品,獲取庫存為2(版本1)

(2)b購買商品,獲取庫存為2(版本1)

(3)a提交訂單,減少庫存,比較版本,一致則執行,庫存減至1(更新後的版本為2)

(4)b提交訂單,減少庫存,比較版本,不一致會阻止執行

<?php

$redis

=new

redis()

;$redis

->

connect

('127.0.0.1'

,6379);

$redis

->

watch

('number');

//在提交時檢測會不會被多人修改,版本是否一致

//從redis中獲得庫存

$number

=$redis

->

get(

'number');

if($number

<=0)

$redis

->

multi()

;//標記乙個事務塊的開始

$redis

->

decr

('number');

//redis內庫存減少

$result

=$redis

->

exec()

;//結束,檢測版本號,不一致會阻止執行if(

$result)(

//mysql操作

)

至於為什麼不使用悲觀鎖和佇列

1、不使用悲觀鎖,因為等待時間非常長,響應慢

2、不使用佇列,因為併發量會讓佇列記憶體瞬間公升高

以上就是php+redis實現秒殺的思路,實際的業務處理會更複雜,酌情參考。

php redis解決高併發案例

本指令碼依賴 php redis擴充套件,請自行安裝 商品 class good public function get string name throw new exception method not exists name todo implement get method.增加庫存 par...

高併發下搶購

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

高併發下的HashMap

1.hashmap在插入元素過多的時候需要進行resize,resize的條件是 hashmap.size capacity loadfactor。2.hashmap的resize包含擴容和rehash兩個步驟,rehash在併發的情況下可能會形成鍊錶環 hashmap進行儲存時,假設size超過當...