php 併發場景的幾種解決方案
在秒殺,搶購等併發場景下,可能會出現超賣的現象,在 php 語言中並沒有原生提供併發的解決方案,因此就需要借助其他方式來實現併發控制。
列出常見的解決方案有:
使用佇列,額外起乙個程序處理佇列,併發請求都放到佇列中,由額外程序序列處理,併發問題就不存在了,但是要額外程序支援以及處理延遲嚴重,本文不先不討論這種方法。
利用資料庫事務特徵,做原子更新,此方法需要依賴資料庫的事務特性。
借助檔案排他鎖,在處理下單請求的時候,用 flock 鎖定乙個檔案,成功拿到鎖的才能處理訂單。
一、利用 redis 事務特徵
redis 事務是原子操作,可以保證訂單處理的過程中資料沒有被其它併發的程序修改。
示例**:
<?php
$http = new swoole_http_server("0.0.0.0", 9509); // 監聽 9509
));$http->on('request', function (swoole_http_request $request, swoole_http_response $response) -"; // 表示當前訂單,被當前使用者搶到了
// do something ... 主要是模擬使用者搶到單後可能要進行的一些密集運算
$rand = rand(100, 1000000);
$sum = 0;
for ($i = 0; $i < $rand; $i++)
// redis 事務
$redis->multi();
$redis->lpush('uniqids', $value);
$redis->decr('rest_count');
$replies = $redis->exec(); // 執行以上 redis 事務
// 如果 rest_count 的值被其它的併發程序更改了,以上事務將回滾
if (!$replies) 回滾" . php_eol;}}
$redis->unwatch();
});
$http->start();在這裡插入**片
使用 ab 測試
$ ab -t 20 -c 10
二、利用檔案排他鎖 (阻塞模式)
阻塞模式下,如果程序在獲取檔案排他鎖時,其它程序正在占用鎖的話,此程序會掛起等待其它程序釋放鎖後,並自己獲取到鎖後,再往下執行。
示例**:
}// 訂單處理完成後,再釋放鎖
flock($fp, lock_un);
}fclose($fp);
});$http->start();使用 ab 測試
$ ab -t 20 -c 10
三、利用檔案排他鎖 (非阻塞模式)
非阻塞模式下,如果程序在獲取檔案排他鎖時,其它程序正在占用鎖的話,此程序會馬上判斷獲取鎖失敗,並且繼續往下執行。\
示例**:
}// 訂單處理完成後,再釋放鎖
flock($fp,lock_un);
} else - 系統繁忙,請稍後再試".php_eol;
}fclose($fp);
});$http->start();使用 ab 測試
$ ab -t 20 -c 10
最後給出三種處理方式的測試結果比較
redis 事務方式:
…concurrency level: 10
time taken for tests: 20.005 seconds
complete requests: 17537
failed requests: 0
total transferred: 2578380 bytes
html transferred: 0 bytes
requests per second: 876.62 [#/sec] (mean)
time per request: 11.407 [ms] (mean)
time per request: 1.141 [ms] (mean, across all concurrent requests)
transfer rate: 125.86 [kbytes/sec] received
…檔案排他鎖(阻塞模式):
…concurrency level: 10
time taken for tests: 20.003 seconds
complete requests: 8205
failed requests: 0
total transferred: 1206282 bytes
html transferred: 0 bytes
requests per second: 410.19 [#/sec] (mean)
time per request: 24.379 [ms] (mean)
time per request: 2.438 [ms] (mean, across all concurrent requests)
transfer rate: 58.89 [kbytes/sec] received
…檔案排他鎖(非阻塞模式):
…concurrency level: 10
time taken for tests: 20.002 seconds
complete requests: 8616
failed requests: 0
total transferred: 1266846 bytes
html transferred: 0 bytes
requests per second: 430.77 [#/sec] (mean)
time per request: 23.214 [ms] (mean)
time per request: 2.321 [ms] (mean, across all concurrent requests)
transfer rate: 61.85 [kbytes/sec] received
…經測試結果對比,redis 事務方式優於檔案排他鎖方式,而檔案排他鎖方式中,非阻塞模式優於阻塞模式。
php併發解決方案
事務不能解決併發,只能保證在乙個事務內所有操作的一致性 常見的併發處理如下 1.悲觀鎖 為什麼叫悲觀鎖?預設每次的執行都會發生併發 表必須是innodb型別,必須在事務中執行,加上for update 查詢的表id 10資料是,這條資料就被鎖定了,第乙個人獲得鎖,後面的人只能等待第乙個人完成事務提交...
PHP 處理併發場景時的3種解決方案
在秒殺,搶購等併發場景下,可能會出現超賣的現象,在 php 語言中並沒有原生提供併發的解決方案,因此就需要借助其他方式來實現併發控制。列出常見的解決方案有 可以使用rabitmq,redis等實現佇列,額外起乙個程序處理佇列,併發請求都放到佇列中,由額外程序序列處理,併發問題就不存在了,但是要額外程...
php高併發解決方案
最近在做乙個 專案,遇到個問題,就是在搶購 秒殺 等活動時,庫存數量有限,但是同時下單人數超過了庫存數量,就會導致商品超售問題。那麼我們怎麼來解決這個問題呢,我的思路如下 sql1 查詢商品庫存 if 庫存數量 0 當沒有併發時,上面的流程看起來是如此完美,假設同時兩個人下單,而庫存只有1個了,在s...