PHP 併發場景的幾種解決方案

2021-09-25 14:21:11 字數 4081 閱讀 2004

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...