Swoole毫秒定时器和高性能内存表 - 深度探索与实践

silverwq
2022-10-13 / 0 评论 / 219 阅读 / 正在检测是否收录...

定时器

我们工作中,定时器经常使用的是contab,但是这个只支持秒级别的,所以我们可以通过swoole的毫秒级别的定时器。
下例中:

  1. 我们可以通过tick来设置定时器,并且还可以传入参数
  2. 使用clear来清除定时器,被清除的定时器就不会执行了
  3. 可以使用after来设置多少秒后执行
  4. 可以用info方法,获取定时器的信息
  5. 可以用clearAll方法来清除所有定时器
use Swoole\Coroutine;
use Swoole\Timer;

Coroutine\run(function () {
    // 创建2秒定时器
    Timer::tick(2000, function (int $timerId, $param1, $param2) {
        echo "定时器,定时器ID是:{$timerId},在2000ms后执行;参数1是:{$param1},参数2是:{$param2}", PHP_EOL;
        Timer::clear($timerId);
        // 2秒定时器里又创建一个4秒的定时器
        Timer::tick(4000, function ($timerId) {
            echo "定时器里的定时器,定时器ID是:{$timerId},在4000ms后执行", PHP_EOL;
            Timer::clear($timerId);
        });
    }, "A", 'B'); // A,B是参数,传递给$param1、$param2

    // 如果只想执行一次,可以用after
    Timer::after(3000, function () {
        echo "通过after触发的定时器,在3000ms后执行", PHP_EOL;
    });

    foreach (Timer::list() as $timerId) {
        echo "这里是循环", PHP_EOL;
        print_r(Timer::info($timerId));
    }

    // 如果清除所有的定时器,那么所有定时器都不会执行,因为都被清除了
    // Timer::clearAll();
});

高性能内存表

内存表,可以理解成mysql的数据表

use Swoole\Table;

// 实现一个类似redis key
$table = new Table(3072);
// 内存表增加列
$table->column('id', Table::TYPE_INT);
$table->column('name', Table::TYPE_STRING, 60);
$table->column('price', Table::TYPE_FLOAT);
// 创建内存表。定义好表的结构后,执行 create 向操作系统申请内存,创建表
$table->create();

$server = new Swoole\Server('127.0.0.1', 9502);
$server->set([
    // 多个进程的负载均衡策略,例如轮询、ip hash、worker进程空闲状态来
    'dispatch_mode' => 1,
]);
$server->table = $table;

$server->on('receive', function ($server, $fd, $reactorId, $data) {
    $cmd = explode(' ', trim($data));
    if ($cmd[0] == 'get') {
        if (count($cmd) < 2) {
            $cmd[1] = $fd;
        }
        $get_fd = intval($cmd[1]);
        // 获取一行数据
        $info = $server->table->get($get_fd);
        $server->send($fd, var_export($info, true) . PHP_EOL);
    } elseif ($cmd[0] == 'set') {
        // 设置行的数据。Table 使用 key-value 的方式来访问数据
        // 返回成功或者失败
        $ret = $server->table->set($fd, [
            'price' => rand(1, 100),
            'id' => $fd,
            'name' => $cmd[1],
        ]);
        if ($ret) {
            $server->send($fd, "OK" . PHP_EOL);
        } else {
            $server->send($fd, "ERROR" . PHP_EOL);
        }
    } else {
        $server->send($fd, "COMMAND ERROR" . PHP_EOL);
    }
});

$server->start();

// 然后在telnet里输入:set 1和get 1试下

优点是:

  1. 读写速度很快,比如redis都还快;
0

评论 (0)

取消