首页 > 解决方案 > 当我使用 Linux task-crontab 时如何同时解决多个问题

问题描述

这里有一个问题:我需要执行一个任务,每分钟将许多数据放入另一个 mysql 数据库;如果第一个任务尚未完成,则第二个任务开始;因此,存在多个并发问题;如何解决问题?

我有一些想法,第一,让任务的执行时间小于下一个任务的开始时间;第二,让任务支持多进程;但是,我不知道如何编写代码?

 public function execute(Input $input, Output $output)
 {
    $tele_data = Telesales::field('*')->where([['create_time','<',time()-48*3600],['customer_label','in',[2,6,7]],['virtual_sale','=','0']])->whereRaw('phone is not null')->select()->toArray();

    foreach($tele_data as $key=>$value) {
        static::pushTeleToIdc($value);
    }
}


private static function pushTeleToIdc($data = []) {

    $res = Telesales::where('id',$value['id'])->update(['virtual_sale'=>'1']);
    if(!$res) {
        return;
    }
    $url = config('idc.tele_url');
    $key = config('idc.tele_key');
    $channel = config('idc.tele_channel');
    $time = time();
    $sign = md5($key.$channel.$time);
    $urls = $url."?channel=".$channel."&sign=".$sign."&time=".$time;
    $require_params = config('idc.require_params');
    foreach($require_params as $key=>$value) {
        if(array_key_exists($key,$data) && !empty($data[$key])) {
            $d[$key] = $data[$key];
        }else{
            $d[$key] = empty($value)?'':$value[array_rand($value,1)];
        }
    }

    $d['register_time'] = $d['create_time'];

    $res =  post_url($urls,$d);
    $result = json_decode($res,true);
    if (isset($result['code']) && $result['code'] != 0){
        Log::init(['single'=>'tpushidc'])->error($res);
    }
}

你能帮我解决问题吗?

标签: phpcron

解决方案


最简单的做法是设置一个标志来告知进程已经在进行中,并在函数开始时检查是否是这种情况。我不知道你想如何设置代码的可见性,所以我留给你将 $myFile 提取到文件/类范围(文件路径也是如此,你可能想要使用一些 /var 或 /这些东西的日志文件夹)。

所以要点是:我们创建一个文件,如果它不存在或其中有一个 0 - 这意味着我们可以开始工作。另一方面,如果文件的内容为 1,则进程会死掉,每次运行它都会死掉,直到第一个完成并将文件的内容重写为 0(这意味着进程不在进步了)。

public function execute(Input $input, Output $output)
{
    if ($this->isProcessInProgress()) {
        die('Process is in progress');
    }

    $this->startProcess();

    $tele_data = [...];

    foreach($tele_data as $key=>$value) {
        static::pushTeleToIdc($value);
    }

    $this->finishProcess();
}

private function isProcessInProgress() {
    $myFile = 'tele_to_idc_process.txt';
    $handle = fopen($myFile, 'r');

    if (!$handle)
        return false;

    $status = fread($handle, 1);
    fclose($handle);

    return (bool) $status;
}

private function startProcess() {
    $myFile = 'tele_to_idc_process.txt';
    $handle = fopen($myFile, 'w');

    if (!$handle)
        return;

    $status = fwrite($handle, '1');

    fclose($handle);
}

private function finishProcess() {
    $myFile = 'tele_to_idc_process.txt';
    $handle = fopen($myFile, 'w');

    if (!$handle)
        return;

    $status = fwrite($handle, '0');

    fclose($handle);
}

如果文件不存在,您可能会收到警告,您可以使用 @fopen 而不是 fopen 来禁止它


推荐阅读