PHP如何限制定時(shí)任務(wù)的進(jìn)程數(shù)量
前言
現(xiàn)在的工作中,經(jīng)常要寫一些腳本做一些異步的操作。
一般是大量的數(shù)據(jù)修改,或者解決部分并發(fā)問(wèn)題。
為了能夠穩(wěn)定的做好數(shù)據(jù)處理,一般情況下會(huì)用定時(shí)腳本的方式。
那么問(wèn)題來(lái)了。
可能存在的問(wèn)題
當(dāng)我們處理大量數(shù)據(jù)的時(shí)候,腳本的執(zhí)行時(shí)間可能很長(zhǎng),或者重復(fù)處理某條數(shù)據(jù)(寫錯(cuò)的情況下)。
為了避免數(shù)據(jù)的重復(fù)處理、運(yùn)行腳本過(guò)多導(dǎo)致服務(wù)器壓力過(guò)大等問(wèn)題,我們需要限制腳本的運(yùn)行數(shù)量。
如何做
思路一
查詢某種標(biāo)識(shí)的進(jìn)程數(shù)量,如果超過(guò)一定數(shù)量,則直接退出,不處理。
思路二
記錄每次的PID,可以使用 文件、redis、memcached 等來(lái)存儲(chǔ)。
當(dāng)啟動(dòng)一個(gè)新進(jìn)程的時(shí)候,去查一下這個(gè)標(biāo)識(shí)下面有哪些PID,是否還在運(yùn)行,且與當(dāng)前標(biāo)識(shí)有關(guān)系。
當(dāng)超過(guò)一定數(shù)量的時(shí)候,直接退出,不處理。
實(shí)踐
思路一實(shí)踐
這里通過(guò) linux 的 ps、grep、wc 的命令來(lái)獲取指定標(biāo)識(shí)的運(yùn)行進(jìn)程數(shù)。
<?php
/**
* 是否可以運(yùn)行
*
* @param string $ident 標(biāo)識(shí)
* @param integer $maxNum 最大運(yùn)行數(shù)量
*
* @return bool
*/
function canRun($ident, $maxNum)
{
$cmd = sprintf('ps ax | grep %s | grep -v /bin/sh | grep -v grep | wc -l', $ident);
$fp = @popen($cmd, 'r');
$num = (int)trim(@fread($fp, 2096));
@pclose($fp);
return $num <= $maxNum;
}
思路二實(shí)踐
這里使用 redis 存儲(chǔ) pid 信息。
通過(guò) /proc/{pid}/cmdline 文件檢測(cè)指定進(jìn)程是否還在運(yùn)行。
<?php
/**
* 檢查 pid 是否存活
*
* @param string $pid PID
* @param string $ident 標(biāo)識(shí)
*
* @return bool
*/
function isSurvive($pid, $ident)
{
// 獲取指定pid的cmdline文件
$cmdlinePath = sprintf('/proc/%s/cmdline', $pid);
if (!is_file($cmdlinePath)) {
return false;
}
$cmdline = trim(file_get_contents($cmdlinePath));
// 檢查標(biāo)識(shí)是否在 cmdline 中
return strpos($cmdline, $ident) !== false;
}
/**
* 是否可以運(yùn)行
*
* @param string $ident 標(biāo)識(shí)
* @param integer $maxNum 最大運(yùn)行數(shù)量
*
* @return bool
*/
function canRun($ident, $maxNum)
{
// 假設(shè)已經(jīng)鏈接上
$redisHandler = getRedis();
// 定義一個(gè)key
$key = sprintf('php:job:%s:pid', $ident);
// 當(dāng)前的PID
$currentPid = getmypid();
// 將當(dāng)前的PID寫入redis
$redis->sAdd($key, $currentPid);
// 獲取redis中的所有pid
$pids = $redis->sMembers($key);
// 遍歷pid,檢查是否有效
foreach ($pids as $index => $pid) {
if ($currentPid == $pid) {
continue;
}
// 檢查 pid 是否還在運(yùn)行中
if (isSurvive($pid, $ident)) {
continue;
}
// 若不再運(yùn)行,則直接刪除
unset($pids[$index]);
$redis->sRemove($key, $pid);
}
return count($pids) <= $maxNum;
}
關(guān)于標(biāo)識(shí)
關(guān)于標(biāo)識(shí),可能我們?cè)谶\(yùn)行一些定時(shí)腳本的時(shí)候,統(tǒng)一的部分可能就是 php 了;或者,擁有相同標(biāo)識(shí)的腳本,我們要?dú)w為幾類。
為了能夠?qū)崿F(xiàn)這些需求,我們可以通過(guò) php 的內(nèi)置函數(shù) cli_set_process_title 來(lái)實(shí)現(xiàn)自定義 COMMAND。
demo.php:
這個(gè)時(shí)候,我們運(yùn)行 demo.php,然后通過(guò) ps ax 可以看到如下結(jié)果:
PID USER TIME COMMAND
1 root 0:09 php-fpm: master process (/usr/local/etc/php-fpm.conf)
7 root 0:16 php-fpm: pool www
8 root 0:15 php-fpm: pool www
9 root 0:14 php-fpm: pool www
10 root 0:00 sh
663 root 0:00 sh
690 root 0:00 {php} Job Demo
691 root 0:00 ps ax
修改指定腳本的進(jìn)程標(biāo)題,我們就可以實(shí)現(xiàn)定義某些腳本的標(biāo)識(shí)了。
最后
沒 BUG 的功能,也可能出現(xiàn) BUG,我們需要更多的思考和設(shè)計(jì)減少這類錯(cuò)誤的發(fā)生。
到此這篇關(guān)于PHP如何限制定時(shí)任務(wù)進(jìn)程數(shù)量的文章就介紹到這了,更多相關(guān)PHP限制進(jìn)程數(shù)量?jī)?nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- php多進(jìn)程中的阻塞與非阻塞操作實(shí)例分析
- php多進(jìn)程并發(fā)編程防止出現(xiàn)僵尸進(jìn)程的方法分析
- PHP多進(jìn)程編程之僵尸進(jìn)程問(wèn)題的理解
- PHP多進(jìn)程之pcntl_fork的實(shí)例詳解
- PHP基于文件鎖解決多進(jìn)程同時(shí)讀寫一個(gè)文件問(wèn)題示例
- PHP守護(hù)進(jìn)程的兩種常見實(shí)現(xiàn)方式詳解
- php中實(shí)現(xiàn)進(jìn)程鎖與多進(jìn)程的方法
- PHP多進(jìn)程編程總結(jié)(推薦)
- 詳解PHP調(diào)用Go服務(wù)的正確方式
相關(guān)文章
學(xué)習(xí)php設(shè)計(jì)模式 php實(shí)現(xiàn)策略模式(strategy)
這篇文章主要介紹了php設(shè)計(jì)模式中的適配器模式,使用php實(shí)現(xiàn)適配器模式,感興趣的小伙伴們可以參考一下2015-12-12
PHP中加密解密函數(shù)與DES加密解密實(shí)例
這篇文章主要介紹了PHP中加密解密函數(shù)與DES加密解密,以實(shí)例形式分析了常用的PHP加密解密算法encrypt與DES加密解密的原理及應(yīng)用方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2014-10-10
PHP使用緩存即時(shí)輸出內(nèi)容(output buffering)的方法
這篇文章主要介紹了PHP使用緩存即時(shí)輸出內(nèi)容(output buffering)的方法,實(shí)例分析了php緩存輸出的相關(guān)使用技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-08-08
phpmyadmin顯示utf8_general_ci中文亂碼的問(wèn)題終級(jí)篇
自己寫PHP也有一年多了,然后編碼問(wèn)題卻老是沒有得到好的解決,自己的情況是這樣的,網(wǎng)頁(yè)顯示完全正常,在phpmyadmin數(shù)據(jù)庫(kù)顯示中文亂碼,不管是簡(jiǎn)體還是繁體,只要是中文都是亂碼2013-04-04
PHP實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)的多種方法
PHP被許多程序員用來(lái)開發(fā)WEB的首選語(yǔ)言,在實(shí)際開發(fā)中,網(wǎng)站的各項(xiàng)功能都可以通過(guò)PHP語(yǔ)言的編寫來(lái)滿足,比如PHP頁(yè)面跳轉(zhuǎn)這一方法,本文給大家介紹了PHP實(shí)現(xiàn)頁(yè)面跳轉(zhuǎn)的多種方法,需要的朋友可以參考下2024-10-10

