基於redis的 sorted set + hash,實現定時執行任務的Demophp
sorted set 介紹:git
思路:github
php實現代碼DEMOweb
<?php class DoTest { private const YIELD_KEY = 'yield:list'; private const YIELD_DATA_KEY = 'yield:data'; public function run() { $bbj = RedisClient::instance()->bbj(); //獲取排序(低到高)中第一個task_id $data = $bbj->zRange(self::YIELD_KEY, 0, 0, true); if (empty($data)) { echo "無數據" . PHP_EOL; return null; } $mem = array_keys($data)[0]; $ts = array_values($data)[0]; $now = time(); //校驗是否到時 if ($ts > $now) { echo "還未到時間,無需操做" . PHP_EOL;; return null; } //移除集合,多進程並執行到時任務(只能被成功移除一次) $row = $bbj->zRem(self::YIELD_KEY, $mem); if (empty($row)) { echo "已經被剔除" . PHP_EOL;; return false; } //獲取當前要執行的任務數據JSON $dataJson = $bbj->hGet(self::YIELD_DATA_KEY, $mem); //todo 執行定時任務業務邏輯 var_export($data); var_export($dataJson); //使用完後刪除任務數據JSON $bbj->hdel(self::YIELD_DATA_KEY, $mem); return true; } public function add(int $time, $i, string $content) { $data = [ 'msg' => $content . $time ]; $bbj = RedisClient::instance()->bbj(); $dataJson = json_encode($data); $taskId = $time . '_' . $i; $isSc = $bbj->zAdd(self::YIELD_KEY, $time, $taskId); if ($isSc) $isSc = $bbj->hSet(self::YIELD_DATA_KEY, $taskId, $dataJson); var_export($isSc); } public function addFeature($i) { $time = Carbon::now()->addMinute()->timestamp; $this->add($time, $i, '將來執行內容'); } public function addCurrent($i) { $time = time(); $this->add($time, $i, '立刻執行內容'); } /** * 取消定時任務,根據任務ID * @param $taskId */ public function removeYield($taskId) { $bbj = RedisClient::instance()->bbj(); $bbj->zRem(self::YIELD_KEY, $taskId); $bbj->hDel(self::YIELD_DATA_KEY, $taskId); } }
監控定時任務隊列redis
<?php $dt = new DoTest(); while (true) { $rt = $dt->run(); if (is_null($rt)) { sleep(1); } }
添加當前執行和將來執行任務json
<?php $dt = new DoTest(); while (true) { for ($i = 0; $i < 100000; $i++) { // 添加當即執行當前任務 $dt->addCurrent($i); // 添加待執行將來任務 $dt->addFeature($i); } }
取消定時任務異步
<?php $dt = new DoTest(); $dt->removeYield('taskId');
首發於Github🌈大話WEB開發,歡迎Star 🥰this