2つの予防crontabはタスクポリシーを繰り返し実行します

2795 ワード

ケーススタディ
フロントは非同期でクラウドのバックグラウンドcronにファイルをアップロードします
*/10 * * * * /usr/local/bin/php /path/to/upload.php  >> /tmp/apkqueue.log

クラウドにファイルをアップロードするのに時間がかかる場合があります.1つのcronがまだ走っていないので、次のcronが開き、1つのファイルが1つのcronよりも大きく同時にアップロードされる可能性があります.
1つのスクリプトの実行時間がcronの間隔よりも大きい場合、同じスクリプトが複数同時に実行されます.また、スクリプトのサブタスクにロックがかかっていない場合は、同じデータが表示されます.
複数のcronによって実行され、システム資源の浪費をもたらす.解決策は、ロック制御が同じスクリプトでシステム内でいつでも1つのプロセスだけで実行され、ロックの粒度によって異なる制御が可能になることです.
以下は私が知っている2つの戦略です.
1、実行するスクリプトのロック
lockf,flock
例:
* * * * * /usr/bin/flock -xn /tmp/full_diff.lock -c 'cd /usr/local/www/admin; /usr/local/bin/php upload.php > /dev/null 2>&1'

30 * * * * (/usr/bin/lockf -s -t 0 /tmp/cdn.push.lock /usr/local/bin/php /path/to/upload.php >> /tmp/log 2>&1)

2、スクリプトにロックをかける
"/tmp/lock.txt", "w+");
if (flock($fp, LOCK_EX | LOCK_NB)) { //        
  	run(); //    
	flock($fp, LOCK_UN); //     
} else {
	echo "Couldn't lock the file !";
}
fclose($fp);
?>

2,サブタスクにロックをかける(ある場合)
mysqlのinnodb update操作は行ロックであり、この点を利用してサブタスクをロックすることができ、1つのデータはサブタスクを表す.
これにより、サブタスクをより西の粒度で制御し、同じ時点で1つのプロセスだけが実行され、複数のプロセスを開くことができます.
function run($procid=0)//       id
{
	$procNum = 10;//   10   


	$data = select(..) from .. where id%$procNum=$procid;
	foreach($data as $row){
		exec($row);
	}



}


function exec($val)
  {
            //lock
            if(model()->lock($val['id'])) //    update table set status='lock' where id=12312 and status='unlock';
                return;
		...run..
            model()->succ($val['id']);

    }


crontab


0 * * * * /proc id=0
1 * * * * /proc id=1
2 * * * * /proc id=2
...
9 * * * * /proc id=9