esd / hashed-wheel-timer-plugin
HashedWheelTimer延迟任务
0.6
2019-06-27 08:37 UTC
Requires
- ext-bcmath: *
- esd/esd-coroutine: ~0.8
- esd/redis-plugin: ~0.19
This package is auto-updated.
Last update: 2024-09-27 20:48:45 UTC
README
HashedWheelTimer是一种使用定时轮的方式来管理和维护大量Timer调度算法的技术。一个HashedWheelTimer是环形结构,类似时钟,分为多个槽位,每个槽位代表一个时间间隔。每个槽位对应一个类似Map结构的对象,使用双向链表存储定时任务,指针周期性地跳动。跳动到一个槽位时,就执行该槽位的定时任务。环形结构可以根据超时时间的hash值(这个hash值实际上是ticks & mask)将task分布到不同的槽位中。当tick到那个槽位时,只需要遍历那个槽位的task即可知道哪些任务会超时(而使用线性结构,你每次tick都需要遍历所有task)。因此,当我们任务量较大时,相应地增加wheel的ticksPerWheel值,可以减少tick时遍历任务的个数。
本插件模拟java HashedWheelTimer的实现。使用redis做持久存储。
配置方法
配置一个环形结构池
hashedWheelTimer:
db: default
max_pending_timeouts: 100
wheel:
- {name: aaa, tick_duration: 1, ticks_per_wheel: 60 }
name 池子名称,投递任务时需要
tick_duration,时间间隔,1秒
ticks_per_wheel,时间槽数量,60个,代表一分钟一个轮次
max_pending_timeouts,每个槽允许的最大协程数,默认100,如果耗时任务或队列特别长需要适当增加时间槽数量,如3600。不适合特别精准的延时场景。
db,使用的redis配置,强烈建议不要使用default,会占用http服务的连接数,应该复制一份配置专用
使用方法
投递任务
//环形池名称,执行任务的类,投递参数,延迟执行时间,秒
$this->addTask('aaa', TimerTask::class,['a'=>'b', 'time' => time()], 60);
投递类
投递的类需要继承HashedWheelTimerRunnable
<?php
namespace app\Controller;
use ESD\Plugins\HashedWheelTimer\HashedWheelTimerRunnable;
class TimerTask extends HashedWheelTimerRunnable{
public function run()
{
/**
//此处可根据延迟次数设置不同的延迟时间,比如支付通知失败
if($this->getDelayTimes() <= 1){
$this->setDelayTTL(10);
}else if ($this->getDelayTimes() <= 2){
$this->setDelayTTL(20);
} else if ($this->getDelayTimes() <= 3){
$this->setDelayTTL(30);
} else if ($this->getDelayTimes() <= 4){
$this->setDelayTTL(40);
}else if ($this->getDelayTimes() <= 5){
$this->setDelayTTL(40);
}
* **/
//如果 return false 或者该类触发任意异常,系统会将此任务重新投递到下一次执行的位置。
//如果不需要失败重试,需要 return true。可通过 getRetryTimes 获取重试次数进行判断
//如超过5次则不再重试,直接return true。
$this->getRetryTimes()
//获取投递参数
$params = $this->getParams();
// TODO: Implement run() method.
$this->info('run', $params);
//如果执行 setDelayTTL , 需要return true ,否则会被重新投递到下一次执行的位置。
return true;
}
}