php 3600环形定时队列
<?php //2021-07-13 13:42:27 namespace app\user\service; use think\cache\driver\Redis; use think\Db; use think\Config; use think\Log; class CrondService { private $redis; private $key; private $config; public function __construct() { $this->key = 'crond'; $this->config = config('queue'); } public function redis(){ if (empty($this->redis)) { $con = new Redis($this->config); $this->redis = $con->handler(); } return $this->redis; } public function generateData(){ $exist = $this->redis()->exists($this->key); if(!$exist){ for($i=1;$i<=3600;$i++){ $single_key = 'solt_'.$i; $this->redis()->rpush($this->key,$single_key); } }else{ //$this->redis()->delete($this->key); // $info = $this->redis()->lrange($this->key,0,-1); // print_r($info);die; } } public function addcrond($jobinfo,$time){ $exist = $this->redis()->exists($this->key); if(!$exist){ $this->generateData(); } !is_numeric($time) && $time = strtotime($time); if($time<time()) return false; $cycle_num = ceil(($time - time())/3600); $single_key = 'solt_'.(($time - time())%3600); $jobinfo['cycle_num'] = $cycle_num; $rs = $this->redis()->sadd($single_key,serialize($jobinfo)); return $rs; } public function docrond(){ //取出当前任务组节点 $nowjobs_name = $this->redis()->lpop($this->key); //将当前任务节点移动最后 $this->redis()->rpush($this->key,$nowjobs_name); //取出当前任务组所有任务 $nowjobs = $this->redis()->smembers($nowjobs_name); if($nowjobs){ //$this->redis()->delete($nowjobs_name); $dojobs = $leftjobs = []; if($nowjobs){ foreach ($nowjobs as $k=>&$v){ $v = unserialize($v); //任务圈数减1 $v['cycle_num'] = $v['cycle_num'] -1; if($v['cycle_num']<1){ $dojobs[] = $v; unset($nowjobs[$k]); } } unset($v); //需要执行的任务 if($dojobs){ //队列执行 foreach ($dojobs as $job){ //写入队列执行操作 $jobname = $job['job']; unset($job['job']); queue_push('app\common\queue\\'.$jobname, $job, $jobname); } if($nowjobs){ $leftjobs = array_map(function ($tv){ $tv = serialize($tv); return $tv; },$nowjobs); $this->redis()->sadd($nowjobs_name,...$leftjobs); return true; } return true; } }else{ return true; } }else{ return true; } } }
public function test(){ $sv = new \app\user\service\CrondService(); for($i=0;$i<=86400;$i++){ $time = time()+$i; $jobinfo = [ 'job'=>'OrderQueue', 'fun'=>'closeOrder',//订单关闭 'param'=>['orderid'=>rand(1,3600)], ]; $data = $sv->addcrond($jobinfo,$time); } print_r($data); }
<?php /** * usefor:订单任务 * User: 骆云飞 * Date: 2021/09/13 */ namespace app\common\queue; use app\api\service\OrderService; use think\Log; use think\queue\Job; class OrderQueue { /** * 用户日志入库 * @param array $data 内容 * @return */ public function fire(Job $job, $data) { set_time_limit(0); $isJobDone = $this->send($data); if ($isJobDone) { //成功删除任务 $job->delete(); } else { //$job->release(3); $job->release(300 * $job->attempts()); } } /** * 根据消息中的数据进行实际的业务处理 * @param array|mixed $data 发布任务时自定义的数据 * @return boolean 任务执行的结果 */ public function send($data) { $errorstr = ""; try { $fun = array_saft_value($data, 'fun'); if (empty($fun)) { return true; } try { return call_user_func([$this,$fun],$data); } catch (\Exception $ex) { Log::error($ex); } } catch (\Exception $e) { Log::error($e); $errorstr .= $e->getMessage(); } finally { } return true; } public function closeOrder($data){ $id = array_saft_value($data, 'orderid'); if (empty($id)) { return true; } $sv = new OrderService(); $where = []; $where['id'] = ['=',$id]; $where['ispay'] = ['=',0]; $where['status'] = ['=',0]; $where['addtime'] = ['<=',time()-3600]; $m = $sv->Get($where); if (empty($m)) { return true; } return $sv->Update(['status'=>-1],$where); } }