一个批量结算任务的demo
来源:互联网 发布:tensorflow翻译 编辑:程序博客网 时间:2024/05/23 20:42
<?phpclass BaseBatchSettleCommand extends CConsoleCommand{ protected $maxProcessNum = 5; protected $pid=0; protected $numFlag = 50000; protected $loopNum = 1000; protected $start_id=0; protected $end_id=0; protected $is_child = false; protected $base_args = []; protected $pre_process_list=[]; protected $process_start_time = 0; protected $process=null; protected $success_count=0; protected $fail_count=0; protected $discount=0; protected function getBaseArg($arg){ if(isset($this->base_args[$arg])){ return $this->base_args[$arg]; } $class = get_called_class(); $methods = get_class_methods($class); if(in_array('get_'.$arg,$methods)){ $ret = call_user_func([$this,"get_".$arg]); $this->setBaseArg($arg,$ret); return $ret; } return []; } public function setBaseArg($arg,$value){ $this->base_args[$arg]=$value; } protected function output($str) { $content = date('Y-m-d H:i:s') . ' pid:' . $this->pid . ', ' .' command:'.$this->getCommandName().' start:'.$this->start_id.' end:'.$this->end_id.' '. $str . "\n"; echo $content; } public function alert($message){ Yii_Log::warning($this->getCommandName().' err:'.$message); } protected function getCommandName(){ $class = get_called_class(); $res = substr($class,0,strlen($class)-7); return $res; } /** * 4个初始化参数 * 1为起始id * 2为截止id * 3标志是否为子进程,子进程不会在创建子进程 * 4为其他初始化参数,多个参数用下划线隔离 */ protected function createProcess($start_id,$end_id,$ini) { $command = $this->getCommandName(); $processNum = $this->getProcessNum(); if(intval($processNum) > $this->maxProcessNum+1){ $this->output('script process num is max'); //$this->alarm('script process num is max'); return false; } $cmd = "nohup /usr/work/tool/php/bin/php /usr/work/tool/app/depository/protected/commands/crons.php {$command} {$start_id} {$end_id} 1 {$ini} 2>&1 >> /usr/work/tool/log/{$command}.log &"; pclose(popen($cmd, "r")); $this->output('script process: create sub process'); return true; } public function getStartId(){ return $this->start_id; } public function getEndId(){ return $this->end_id; } protected function getList($start,$end){ return []; } protected function getSettleNum(){ } protected function settle($record){ } protected function processStart($args){ } protected function processEnd(){ } protected function getProcessNum(){// $count = 0;// $pid_dir = DATA_DIR.'/command_pid/'.$this->getCommandName();// $list = scandir($pid_dir);// foreach ($list as $value){// if(strpos($value,'.pid')!==false){// $count++;// }// } $rand = rand(100000,500000); usleep($rand); $command = $this->getCommandName(); $count = `ps aux|grep -i "crons.php {$command}"|grep -v "grep"|wc -l`;//没有查表或写文件,因为可能有延时 return intval($count); } private function _processStart($args){// $this->writePidFile(); $this->output('process start args:'.json_encode($args)); $process = new ProcessInfo(); $process->start_id = $this->start_id; $process->end_id = $this->end_id; $process->status = ProcessInfo::STATUS_CREATE; $process->is_child = $this->is_child?1:0; $process->start_time = $this->process_start_time; $process->snap_date = $this->getSnapDate(); $process->pid = $this->pid; $process->command = $this->getCommandName(); $process->save(); $this->process = $process; $this->beforeRun(); $process->status = ProcessInfo::STATUS_RUNNING; $process->save(); try{ $this->processStart($args); }catch (Exception $e){ $this->alert($e->getMessage()); } } private function _processEnd(){ try{ $this->processEnd(); }catch (Exception $e){ $this->alert($e->getMessage()); } $this->process->status = ProcessInfo::STATUS_END; $this->process->success_count = $this->success_count; $this->process->fail_count = $this->fail_count; $this->process->discount = $this->discount; $this->process->end_time = time(); $this->process->save(); if($this->getProcessNum()==1){ $pid_dir = DATA_DIR.'/command_end/'; $file = $this->getCommandName().date('Y-m-d').'.end'; if(!is_dir($pid_dir)){ mkdir($pid_dir); } file_put_contents($pid_dir.$file,$this->pid); } $this->output('process end');// $this->deletePidFile(); }// private function writePidFile(){// $pid_dir = DATA_DIR.'/command_pid/'.$this->getCommandName();// $pid_file = $pid_dir.'/'.$this->pid.'.pid';// if(!is_dir($pid_dir)){// mkdir($pid_dir);// }// file_put_contents($pid_file,$this->pid);// }// private function deletePidFile(){// $pid_dir = DATA_DIR.'/command_pid/'.$this->getCommandName();// $pid_file = $pid_dir.'/'.$this->pid.'.pid';// if(file_exists($pid_file)){// unlink($pid_file);// }// } protected function checkPreProcessEnd(){ if(empty($this->pre_process_list)){ return true; } foreach ($this->pre_process_list as $value){ $pid_dir = DATA_DIR.'/command_end/'; $file = $value.date('Y-m-d').'.end'; if(file_exists($pid_dir.$file)){ return true; } } return false; } private function beforeRun(){ while (true){ if($this->checkPreProcessEnd()){ return; } $this->process->status = ProcessInfo::STATUS_WAITING; $this->process->save(); sleep(10); } } protected function getIni($args){ $ini = $args[3]; if($ini){ return $ini; } } protected function setIni($arg1_arg2){ $args = explode('_',$arg1_arg2); return $args; } public function run($args){ ini_set('memory_limit', '128M'); /**初始化**/ $this->pid = getmypid(); $this->process_start_time = time(); $start_id = $args[0]; $end_id = $args[1]; $is_child = $args[2]?true:false; isset($start_id)&&$this->start_id = $start_id; isset($end_id)&&$this->end_id = $end_id; isset($this->is_child)&&$this->is_child = $is_child; $ini = $args[3]?$args[3]:null; $this->setIni($ini); /**初始化结束**/ $this->_processStart($args); if(!isset($start_id)){ $start_id = $this->getStartId(); } if(!isset($end_id)){ $end_id = $this->getEndId(); } if($end_id-$start_id>$this->numFlag&&$is_child==false){ //大于10万条数据分子进程加速处理 $max_num = $this->maxProcessNum; $gap = ceil(($end_id-$start_id+1)/$max_num); $ini = $this->getIni($args); for($i=$start_id;$i<=$end_id;$i+=$gap){ $end = $i+$gap-1; $end>$end_id&&$end = $end_id; $this->createProcess($i,$end,$ini);//取闭区间 } $this->_processEnd(); return ; } $current = $start_id + $this->loopNum-1; $current>$end_id&&$current=$end_id; while ($start_id<=$end_id){ echo 'start,id:'.$start_id."\t 'end,id:$current\t time:".date('Y-m-d H:i:s')."\n"; if(!$this->checkRunTime()){ $this->alert('执行时间过长'); $this->_processEnd(); return; } $list = $this->getList($start_id,$current);//取闭区间 $current+=$this->loopNum; $start_id+=$this->loopNum; $current>$end_id&&$current=$end_id; foreach ($list as $value){ try{ $this->settle($value); }catch (Exception $e){ $this->fail_count++; $this->alert('error:'.$e->getMessage()); } } $this->process->success_count = $this->success_count; $this->process->fail_count = $this->fail_count; $this->process->discount = $this->discount; $this->process->save(); } $this->_processEnd(); } protected function checkRunTime(){ return true; $timestamp = $this->getSnapDate(); if(time()-$timestamp>=85000){//时间跨度不超过1天 return false; } return true; } protected function getSnapDate(){ $run_date = date('Y-m-d',$this->process_start_time); $timestamp = strtotime($run_date); return $timestamp; }}
阅读全文
0 0
- 一个批量结算任务的demo
- 【】mysql结算批量处理的优化
- 一个无限批量下载百度美女图片的demo
- 一个关于工资结算的小程序
- Apex学习:一个计划任务与批处理的Demo
- 一个适合绝大多数场景下的批量任务线程池
- 一个简单的购物车结算js分享
- 异步任务AsyncTask的Demo
- Spring定时任务的Demo
- oracle的定时任务demo
- 定时任务,quartz的demo
- 理财平台C++定时结算任务的容灾问题的解决方案
- quartz简单demo(一个简单易用的任务调度开源框架)
- 国际结算的读书笔记
- 订单的结算日期
- 结算平台的搭建
- MapBar的一个Demo
- wxMenu的一个demo
- 功率放大电路
- fiddler- 手机端抓包
- VUE中子组件向父组件传递事件
- Android 简单GreenDao增删改查
- 机器学习高斯混合模型:聚类原理分析(前篇)
- 一个批量结算任务的demo
- Super Mario(线段树 + 离散化)
- mybatis+spring+ehcache缓存
- 小程序中吸底按钮适配 iPhone X 方案
- Linux系统换源
- C#winForm程序与html JS交互调用
- C语言回车符的小trick
- [nodejs][express]监听
- 循环神经网络(RNN)原理通俗解释