分类 Swoole 下的文章

<?php
/**
 * MineAdmin is committed to providing solutions for quickly building web applications
 * Please view the LICENSE file that was distributed with this source code,
 * For the full copyright and license information.
 * Thank you very much for using MineAdmin.
 *
 * @Author X.Mo<root@imoi.cn>
 * @Link   https://gitee.com/xmo/MineAdmin
 */

namespace Mine\Redis;

use Hyperf\Utils\Coroutine;
use Mine\Abstracts\AbstractRedis;
use Mine\Exception\NormalStatusException;
use Mine\Interfaces\MineRedisInterface;

class MineLockRedis extends AbstractRedis implements MineRedisInterface
{
    /**
     * 设置 key 类型名
     * @param string $typeName
     */
    public function setTypeName(string $typeName): void
    {
        $this->typeName = $typeName;
    }

    /**
     * 获取key 类型名
     * @return string
     */
    public function getTypeName(): string
    {
        return $this->typeName;
    }

    /**
     * 运行锁,简单封装
     * @param \Closure $closure
     * @param string $key
     * @param int $expired
     * @param int $timeout
     * @param float $sleep
     * @return bool
     * @throws \Throwable
     */
    public function run(\Closure $closure, string $key, int $expired, int $timeout = 0, float $sleep = 0.1): bool
    {
        if (! $this->lock($key, $expired, $timeout, $sleep)) {
            return false;
        }

        try {
            call_user_func($closure);
        } catch (\Throwable $e) {
            logger('Redis Lock')->error(t('mineadmin.redis_lock_error'));
            throw new NormalStatusException(t('mineadmin.redis_lock_error'), 500);
        } finally {
            $this->freed($key);
        }

        return true;
    }

    /**
     * 检查锁
     * @param string $key
     * @return bool
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function check(string $key): bool
    {
        return redis()->exists($this->getKey($key));
    }

    /**
     * 添加锁
     * @param string $key
     * @param int $expired
     * @param int $timeout
     * @param float $sleep
     * @return bool
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function lock(string $key, int $expired, int $timeout = 0, float $sleep = 0.1): bool
    {
        $retry = $timeout > 0 ? intdiv($timeout * 100, 10) : 1;

        $name = $this->getKey($key);

        while ($retry > 0) {

            $lock = redis()->set($name, 1, ['nx', 'ex' => $expired]);
            if ($lock || $timeout === 0) {
                break;
            }
            Coroutine::id() ? Coroutine::sleep($sleep) : usleep(9999999);

            $retry--;
        }

        return true;
    }

    /**
     * 释放锁
     * @param string $key
     * @return bool
     * @throws \Psr\Container\ContainerExceptionInterface
     * @throws \Psr\Container\NotFoundExceptionInterface
     */
    public function freed(string $key): bool
    {
        $luaScript = <<<Lua
            if redis.call("GET", KEYS[1]) == ARGV[1] then
                return redis.call("DEL", KEYS[1])
            else
                return 0
            end
        Lua;

        return redis()->eval($luaScript, [$this->getKey($key), 1], 1) > 0;
    }

}

先理解几个概念:

1.StdClass 对象 => 基础的对象
2.Eloquent 模型对象 (Model 对象) => 和模型相关的类对象
3.Eloquent 集合 => 可以简单理解为对象数组,里面的每一个元素都是一个 Model 对象

DB Facades

1.$users = DB::table('users')->get(); 返回值:数组结果,其中每一个结果都是 StdClass
2.$user = DB::table('users')->first();返回值:单个 StdClass 实例

Eloquent

1.$user = User::first(); 返回值:Eloquent 对象 `
2.$user = User::find(); 返回值:Eloquent 对象 `
3.$users = User::get(); 返回值:Eloquent 集合
4.$users = User::all(); 返回值:Eloquent 集合
5.$user = User::create($data); 返回值:Eloquent 对象
6.$user = new User(); $user->name = "admin" $user->save(); 返回值:Eloquent 对象
7.$result = User::insert($data); 返回值:bool
8.$result = $user->delete(); 返回值:bool
9.$count = User::destroy([1, 2]); 返回值:删除记录数
10.$count = User::where('id', '>', 1)->delete(); 返回值:删除记录数
11.$count = User::where('id', '>', 10)->update(['status' => 1]);返回值:更新记录数
12.$count = User::where('id', '>', 10)->increment('age', 1);返回值:更新记录数

纯粹为了查阅方便,作者辛苦了!本文转自:
https://learnku.com/articles/15654/laravel-return-value

协程调度

决定到底让 CPU 执行哪个协程的代码决断过程就是协程调度,调度的策略是什么?

首先,在执行某个协程代码的过程中发现这行代码遇到了 Co::sleep() 或者产生了网络 IO,例如 MySQL->query(),这肯定是一个耗时的过程,Swoole 就会把这个 Mysql 连接的 Fd 放到 EventLoop 中。

  • 然后让出这个协程的 CPU 给其他协程使用:即 yield(挂起)
  • 等待 MySQL 数据返回后就继续执行这个协程:即 resume(恢复)

其次,如果协程的代码有 CPU 密集型代码,可以开启 enable_preemptive_schedulerSwoole 会强行让这个协程让出 CPU

摘自:https://wiki.swoole.com/#/coroutine?id=协程调度