乐趣区

关于php:不使用pcntlpthreadsswoole的前提下-laravel该如何实现伪多进程

引言

  • 家喻户晓,多过程 / 多线程能够并行 / 并发的执行多个工作,进步运行效率。
  • PHP 默认是不反对多过程 / 多线程的,须要装置 pcntl/pthreads 扩大来反对。协程如果不必 swoole 等框架,那么实现比较复杂。
  • 以上办法均不应用,那么该如何进步程序的运行效率呢?<!–more–>

思路

  1. 对于耗时的工作, 通常会推送到工作队列中,而后队列生产过程从工作队列中获取工作执行。
  2. 一个队列是能够开启多个生产过程的,那么执行工作的效率是比单个过程程序执行效率多很多的。
  3. 如果不须要期待所有工作的执行实现来获取后果的话,其实开启多个队列生产过程曾经够了。
  4. 如果须要期待所有工作实现才返回后果的操作,比方在定时工作中须要读取 Mysql 的 100 条记录,去调用第三方的 API,这个三方 API 很 Low,调用一次须要 2s,最终须要生成这 100 条记录的 CSV 文件。程序执行至多须要 200s 能力实现, 如果有 4 个队列生产过程, 那么只须要 50s 左右即可实现。
  5. 次要问题在于如何解决过程间通信?因为须要晓得这些子工作是否执行完,以及须要晓得工作的执行后果。那么是否能够将应用 redis 来通信呢?用 redis 进行计数操作,每个工作执行完将计数器加 1,每个工作的执行后果都放在 redis 的 list/hash 中,当计数器的总数等于工作总数的时候,就能够判定工作曾经执行实现,而后取出 redis 寄存的后果,生成 csv 文件。

实现

理论我的项目已在线上稳固跑了几个月了,在这里只贴伪代码展现一下实现思路,有趣味的能够本人实现试试。

  • 定时工作 command,这里次要是程序入口, 设置好计数器, 并且期待队列工作执行实现,获取后果。

  • 具体任务 Job 代码, 次要执行耗时工作,以及执行实现计数器进行加 1,须要留神的是异样也要保障计数器 +1,否则工作总数跟执行总数不相等,那么主过程 command 会卡死。

  • 将工作相干信息保留到 redis 的 hash 数据结构中, 须要保留工作总数的 key, 用于统计的已执行工作总数的 key,计数能够用工夫复杂度为 O(1)的 hincrby 命令。

  • 后果也能够保留到该 hash 中, 通过 hvals 获取后果前先把两个 count 的 key 删除即可。

  • 该代码示例只适宜学习应用,如果须要生产应用须要本人解决细节问题。
  • 开启多个工作队列, 可手动开启几个终端手动执行:php artisan queue:work redis --queue=calculate启动多个队列生产过程,也能够通过 supervisor 来启动, 通过配置 numprocs=8 参数来限度过程数量。
退出移动版