加深下文件鎖理論
flock—輕便的諮詢文件鎖定php
handle
mysql
文件系統指針,是典型地由fopen()建立的resource(資源)。redis
operation
sql
operation
能夠是如下值之一:緩存
LOCK_SH
取得共享鎖定(讀取的程序)。LOCK_EX
取得獨佔鎖定(寫入的程序。LOCK_UN
釋放鎖定(不管共享或獨佔)。若是不但願flock()在鎖定時堵塞,則是LOCK_NB
(Windows 上還不支持)。併發
wouldblock
高併發
若是鎖定會堵塞的話(EWOULDBLOCK 錯誤碼狀況下),可選的第三個參數會被設置爲TRUE
。(Windows 上不支持)性能
成功時返回TRUE
, 或者在失敗時返回FALSE
。優化
$fp =fopen("lock.txt","w+"); //'w+'_讀寫方式打開,將件指針指向文件頭並將文件大小截爲零。若是文件不存在則嘗試建立之。 // 加鎖 if(flock($fp,LOCK_EX|LOCK_NB)){ // 非阻塞模式 // 執行業務邏輯 $res=1; //執行完成解鎖 flock($fp,LOCK_UN); }else { // 其餘進程未解鎖執行 } // 釋放內存 減小502發生 unset($res); $res=null; fclose($fp);
$fp = fopen("lock.txt", "w+"); // 加鎖 if (flock($fp, LOCK_EX)) { // 阻塞模式 // 執行業務邏輯 $res = 1; //執行完成解鎖 flock($fp, LOCK_UN); } // 當前進程會一直等其餘進程解鎖文件後繼續執行 // TODO echo "文件解鎖後才能輸出"; // 釋放內存 減小502發生 unset($res); $res = null; fclose($fp);
在處理搶購、秒殺應用場景下降「超賣」發生幾個優化方案spa
1: 將庫存字段屬性設爲無符號(unsigned),在庫存爲0,不會出現負數
2:利用mysql的事務(鎖定一行)
select **... for update // 鎖定一行,其餘的操做都會被阻塞,直到鎖定的行提交commit ,其實這樣也存在性能問題,阻塞時間漫長以下圖
3:redis隊列(推薦)
lpop,lpush,llen
mysql事務在高併發下性能降低很厲害,文件鎖也是,由於Redis全部單個命令的執行都是原子性的,要麼都執行,要麼都不執行注意在使用redis作緩存時候,在更新商品庫存推薦使用hincrby
例如:
$num=0-$goodsNum; $inventoryNum= $redisObj->hincrby($key, 'num', $num); 同理mysql也是同樣作減法操做
4:使用php文件鎖(阻塞/非阻塞模式)
5:redis鎖處理(推薦)
set方式 setnx方式 setnx+getset方式