任务事件

任务生命周期事件

而可以 Queue::beforeQueue::after
方法来报一个回调在列任务开始之前还是队列执行成功之后调用。回调为补偿加额外的日志,持续执行子任务或多统计信息等提供了那个好之机会。比如,我们可以于
laravel 的 AppServiceProvider
中定义一个任务成功执行后的事件监听,并附加一个回调至事件中:

<?php

namespace App\Providers;

use Queue;
use Illuminate\Support\ServiceProvider;
use Illuminate\Queue\Events\JobProcessed;

class AppServiceProvider extends ServiceProvider
{
  /**
   * Bootstrap any application services.
   *
   * @return void
   */
   public function boot()
   {
     Queue::after(function (JobProcessed $event) {
       // $event->connectionName
       // $event->job
       // $event->data
     });
   }

   /**
    * Register the service provider.
    *
    * @return void
    */
    public function register()
    {
      //
    }
}

INCR/DECR类���

递增操作:INCR INCRBY INCRBYFLOAT
递减操作:DECR DECRBY

只有INCRBYFLOAT而没有DECRBYFLOAT,但是得经用负数做参数实现平等的功能。

安排有守护进程的班监听器

因为队列工作之医护进程是一个常驻进程。它不会见又你的代码改变时开展重复开。所以,你当用安排下本来当代码变更时重新部署使用守护进程的阵工作:

php artisan queue:restart

欠命令会优雅的点队列完成目前之天职后死亡,所以未会见设有任务之落。你应该注意的是,当您行
queue:restart
命令时,队列工作就会见死去,所以若应当使用相同种植进程管理器,比如
Supervisor,你可配备它来机关的重新开队列工作。

在意:该令依赖让缓存系统来制订更开时间表。默认的 APCu 不支持以 CLI
中运行任务。如果您以 APCu,你应当添加 apc.enable_cli=1 到你的 APCu
配置中。

模式-通过Redis实现简单锁
SET lock "anyString" NX EX 10

由此地方的命,可以借助Redis实现锁的效能。当令归来OK代表客户端成功获得到锁;当跨越10秒后,锁会自动释放;客户端也可以由此DEL命令主动释放锁。

粗略锁会在个别只问题:
1、key只出一个;
2、client1取得到锁后,client2可以通过DEL命令释放锁;

改进:
1、key通过随机算法生成字符串;
2、DEL操作前,还得参加Value的比,再做DEL操作;

引用一段子Redis文档中之代码:

if redis.call("get",KEYS[1]) == ARGV[1]
then
    return redis.call("del",KEYS[1])
else
    return 0
end

队列

SET/GET类���

无限简易的SET/GET操作:

SET mykey "hello" => "OK"
GET mykey => "hello"

SET操作会在Redis中创造一个值也hello的key(mykey)。如果key已经存在,它的价将会见于掩。GET操作用于获取mykey对应的值hello。

SET操作可以附加一些参数:

SET mykey "hello" EX 10

EX 10会见招mykey在10秒后失效,超过10秒后使用GET操作会得nil:

GET mykey => "(nil)"

PX 10000EX 10功�能相似,只是岁月单位变成了毫秒。

SET mykey "hello" NX => "OK"
SET mykey "hello" XX => "OK"

NX的语义为当key不存时时才装,XX的语义为当key存在才装,失败时见面回去nil。

Supervisor 配置

Supervisor 是 Linux 操作系统的一个进程监控器,并且她可自动的在
queue:listen 或者 queue:work
命令失败时展开再次开。你可以下的命令于 Ubuntu 中设置 Supervisor:

sudo apt-get install supervisor

Supervisor 配置文件一般都存储于 /etc/supervisor/conf.d
目录中。在此目录中,你可创建任意数量之部署文件来指点 supervisor
来管理监督进程。比如,让咱创建一个 laravel-worker.conf
文件来开始与监控 queue:work 进程:

[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command= php /home/forge/app.com/artisan queue:work sqs --sleep=3 --tries=3 --daemon
autostart=true
autorestart=true
user=forge
numprocs=8
redirect_stderr=true
stdout_logfile=/home/forge/app.com/worker.log

方的例子中,numprocs 会指导 Supervisor 运行 8 个 queue:work
进程而对那进展督查,它见面活动的当其挫败时展开双重开。当然,你可修改命令的
queue:work sqs 部分来利用你所梦想的排驱动。

假如配置文件创建完成,你得运用下的命来更新 Supervisor
的部署文件及开行进程:

sudo supervisorctl reread

sudo supervisorctl update

sudo supervisorctl start laravel-worker:*

有关更多之 Supervisor 的布置信息,请参考 Supervisor
documentation。另外,你啊得使
Laravel Forge
来从一个有利于的 Web 界面自动的安排以及治本而的 Supervisor 配置。

其他

GETSET安装新值,返回老值;
SETRANGE/GETRANGE设置/获取字符串中的同样段落;
STRLEN赢得字符串长度;

编制任务类

另外一样种锁实现
SETNX lock.foo <current Unix time + lock timeout + 1>

倘有client1、client2、client3于竞争锁,只来一个client的SETNX操作会返回1,代表时client获取到锁。client后续可以通过DEL操作释放锁。

死锁问题处理:
1、client1落到锁后crash了;
2、client2通过SETNX操作尝试取锁,但是锁仍旧让client1装有,所有redis返回0;
3、client2通过GET操作,获取lock.foo值中保留之日子穿,与目前时间较,发现锁曾过期;
4、client2发送GETSET lock.foo <current Unix timestamp + lock timeout + 1>操作,并检讨返回值是否还是是过的流年,如果超时说明client2已经获到了锁;
5、如果未是过,说明有另外的client已经修改了光阴穿,client2会从步骤2重新尝试获得锁;

职责类组织

任务类是雅简练的,通常它们独自包含一个 handle
方法来以队任务尽时被调用。我们来拘禁一个简约的天职示例:

<?php

namespace App\Jobs;

use App\User;
use App\Jobs\Job;
use Illuminate\Contracts\Mail\Mailer;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queus\ShouldQueue;

class SendReminderEmail extends Job implements ShouldQueue
{
  use InteractsWithQueue, SerializesModels;

  protected $user;

  /**
   * Create a new job instance.
   *
   * @param User $user
   * @return void
   */
   public function __construct(User $user)
   {
     $this->user = $user;
   }

   /**
    * Execute the job.
    *
    * @param Mailer $mailer
    * @return void
    */
    public function handle(Mailer $mailer)
    {
      $mailer->send('emails.reminder', ['user' => $this->user], function () {
        //
      });

      $this->user->reminders()->create(...);
    }
}

每当是例子中,你需要注意的凡,我们得以一直的于排任务之构造函数中传递一个
Eloquent 模型。因为咱们引入了 SerializesModels
trait,所以当排任务履行时,Eloquent
模型会吃优雅的序列化和倒序列化。如果队列任务在构造器中收了 Eloquent
模型,那么队列任务就见面序列化模型的
ID。而在职责急需展开处理常,队列系统会从数据库被活动的根据 ID
检索出模型实例。这在行使被完全是晶莹剔透底,这样就得避免了序列化完整的型或当班中起的问题。

handle
方法会在排任务执行时展开调用。你用懂得之是,我们好以任务的
handle 方法中得以动用项目提示来进展依赖之流。laravel
的服务容器会自行的以这些靠注入进来。

来酷出

假使任务进展的历程中产生特别被丢掉来。它见面自行的将任务释放,同时多到行列的尾端为要任务可开展双重尝试。该任务会让无休止释放进行尝试除非尝试的次数超过了所设置的无限可怜次数。你可以于排监听器
queue:listen 或者 queue:work Artisan 任务指令中补充加 --tries
选项来安装极端特别可尝次数。我们用于连续篇幅中详细的介绍队列监听器。

手动的放走任务及行列尾端

君得运用 release 方法来进行手动的假释任务。laravel
命令生成的天职类吃早已引入了 InteractsWithQueue
trait,这个特性提供了顾任务队列的 release
方法。该办法接收一个参数:你望任务还可用之间隔(秒):

public function handle(Mailer $mailer)
{
  if (condition) {
    $this->release(10);
  }
}

自我批评职责就尝试的次数

就是如上面我们所言到的,如果在任务拓展的历程中,异常出现,那么队列会自行的放走任务并以任务推送至行列的尾端使其好展开双重尝试。你可经
attempts 方法来检查任务之假释次数:

public function handle(Mailer $mailer)
{
  if ($this->attempts() > 3) {
    //
  }
}
其它操作

BITPOS回第一个受装为0或1的职。

SETBIT pos 10 1 => "(integer) 0"

BITPOS pos 1 => "(integer) 10"

BITPOS的最终两只参数是byte,如果实行以下命令:

BITPOS pos 0 1 => "(integer) 8" 

因限了由第一单字节开始(0计数),所以率先只为0的号的offset是8。

BITOP每当差不多个key之间实行和、或、异或、非等逻辑操作。

简介

laravel 的序列服务对各种不同的后台队列服务提供了统一的
API。队列允许而延缓执行消耗时间之天职,比如发送一封邮件。这样可以使得之落请求响应的岁月。

模式-利用bitmap统计用户访问历史
SETBIT user:yingzong 0 1 => "(integer) 0"

offset
0代表网站及丝的第一天,每天递增1。需要经常好通过BITCOUNT命令统计bitmap中被置为1的位数,代表用户访问数。

复履行破产的职责

汝可以用 queue:failed Artisan 命令来显示数据库 failed_jobs
表中破产的职责:

php artisan queue:failed

queue:failed 命令会列出任务之 ID,连接,队列,和黄时。任务 ID
可以据此来进行破产任务的品味。比如,你可以尝尝重新履行 ID 为 5 的天职:

php artisan queue:retry 5

若得运用 queue:retry all 命令来重新开所有的职责:

php artisan queue:retry all

要是您愿意去失败的任务,你可以 queue:forget 命令:

php artisan queue:forget 5

你可以使 queue:flush 命令来打消所有挫折的任务:

php artisan queue:flush

Strings是Redis支持的极度简易数据类型,以下按SET/GETINCR/DECRBIT
3栽分类介绍字符串格式支持之授命。

运行班监听器

启进行排监听

laravel 包含了一个 Artisan
命令来运转推送至队中之天职的实践。你得下 queue:listen
命令来运作监听器:

php artisan queue:listen

卿吗得以指定监听哪一个总是的队列:

php artisan queue:listen connection-name

您用注意的凡,这个令执行,它会随地的运作,除非你手动的进展悬停。你得通过应用
Supervisor
进程监控来确保队列监听器的运作。

队优先级

公可由此运用 , 来划分连接的行,以确定队列的运作优先级:

php artisan queue:listen --queue=high,low

以斯例子中,任务会优先实施 high 的阵,然后才会运作 low
队列中之天职。

指定任务的过时间

你可以安装任务之超时时间:

php artisan queue:listen --timeout=60

点名队列的睡时

此外,你可以指定队列轮询新的天职要拭目以待的辰(秒):

php artisan queue:listen --sleep=5

君要注意的是,队列只会当班中从来不得实施之天职时才会展开睡眠。如果队列中发出差不多只可实行之职责,那么队列会随地的拓展任务之执行,而未会见进行睡眠操作。

实施队列的首只任务

公可利用 queue:work 命令来仅实行队列的首单任务:

php artisan queue:work
惠及操作BITFIELD

Redis3.2提供了BITFIELD操作,可以以一如既往条指令中实施多单分支的Bitmap操作。

BITFIELD bitkey SET i4 0 5 => "1) (integer) 0"

用bitkey的价,0-3号保存有号整数值5。i4代表4各项产生记号整数,u4表示4各项无符号整数。

BITFIELD bitkey GET i4 => "1) (integer) 5"

获得刚才保存的值。BITFIELD命令可以组成以:

BITFIELD bitkey GET i4 0 SET u4 4 6 INCRBY u4 4 1
=> "1) (integer) 5"
=> "2) (integer) 0"
=> "3) (integer) 7"

另外BITFIELD还提供了三种溢起政策:
WRAP一个i8的平头,值为127,递增1碰头造成价值变为-128;
SAT一个i8的平头,值吗120,递增10会见招致价值变为127;
FAIL发出溢起时操作失败;

BITFIELD bits SET i8 0 127 OVERFLOW WRAP INCRBY i8 0 1
=> "1) (integer) 0"
=> "2) (integer) -128"

配置

列的布文件为积存在 config/queue.php
中。在这文件被君晤面发现框架所支撑之阵驱动之布置连接示例。这些使得包括:数据库,Beanstalkd,Amazon
SQS,Redis,和一个合办(本地使用)的让。

再有一个称也 null 的教表明无下队列任务。

BIT类

Bitmap,一失误连续的二进制数字,可以当极少的上空内进行统计测算。Redis提供了一样组的Bitmap操作。

SETBIT bitkey 10 1 => "(integer) 0"

GETBIT bitkey 10 => "(integer) 1"
GETBIT bitkey 1 => "(integer) 0"

SETBIT的价只能是0或1。当key不存时会创建一个新的string值,Redis会确保string足够保存指定offset的bit。offset的限从0到2^32-1。SETBIT的返回值是借助定offset之前封存之bit。

BITCOUNT bitkey => "(integer) 1"
BITSET bitkey 0 1 => "(integer) 0"
BITCOUNT bitkey => "(integer) 2"

统计bitkey中发生稍许个让置为1。

推迟任务

有时,你也许会见想只要延迟执行队列任务。比如,你或想有一个队任务可以当用户注册后底
5 分钟发送一封闭提醒邮件。你可在职责类中应用 delay
方法来就,该措施是透过 Illuminate\Bus\Queueable 性状提供的:

<?php

namespace App\Http\Controllers;

use App\User;
use Illuminate\Http\Request;
use App\Jobs\SendReminderEmail;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
  /**
   * Send a reminder e-mail to a given user.
   *
   * @param Request $request
   * @param int $id
   * @return Response
   */
   public function sendReminderEmail(Request $request, $id)
   {
     $user = User::findOrFail($id);

     $job = (new SendReminderEamil($user))->delay(60 * 5);

     $this->dispatch($job);
   }
}

在这个例子中,我们指定了职责应当队中延迟 5 分钟实施。

顾: Amazon SQS 服务来极度可怜延迟执行限制,其最多但是缓 15 分钟。

SET的变种兄弟等
SETEX mykey 10 "hello" => "OK"

SET mykey "hello" EX 10有着同等效果。另还有PSETEX令,单位为毫秒。

SETNX mykey "hello" => "(integer) 1"
SETNX mykey "hello" => "(integer) 0"

SET mykey "hello" NX不无同等效果,但回到回值有些区别。

MSETNX key1 "hello" key2 "world" => "(integer) 1"
MSETNX key1 "hello" key3 "test" => "(integer) 0"

GET key3 => "(nil)"  

批量本子的SETNX,只能全部写副成功还是全未果。

以及挫折的天职进行相互

出于众多业务并无可知如计划面临之那么进行,有时候队列任务的实践或者会见败,不要顾虑,它发生对咱们的话是太好的!laravel
包含了同种便民的法门来指定任务应更尝试的次数。如果任务为重新执行到指定的次数,它便会叫记录及
failed_jobs 表中。这个发明底名而得通过 config/queue.php
配置文件进行定制。

你可以使 queue:failed-table 命令来大成一个 failed_jobs 迁移表:

php artisan queue:failed-table

当您运行班监听器时,你可以应用 --tries
选项来指定任务的不过充分尝试次数:

php artisan queue:listen connection-name --tries=3
批量SET/GET
MSET key1 "Hello" key2 "World" => "OK"

MGET key1 key2
=> 1) "Hello"
=> 2) "World"

批量版SET/GET操作,不过大多介绍了。

推送任务交队

位于 app/Http/Controllers/Controller.php 的 laravel 基础控制器采用了
DispatchesJobs
trait。这个特点提供了部分措施允许而方便之推送任务及行列。比如 dispatch
方法:

<?php

namespace App\Http\Controllers;

use App\User;
use Illuminate\Http\Request;
use App\Jobs\SendReminderEmail;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
  /**
   * Send a reminder e-mail to a given user.
   *
   * @param Request $request
   * @param int $id
   * @return Response
   */
   public function sendReminderEmail(Request $request, $id)
   {
     $user = User::findOrFail($id);

     $this->dispatch(new SendReminderEmail($user));
   }
}

DispatchesJobs 性状

本来,有时候你或希望于利用中之别样地方进行任务之分发,而不仅只有在行程由于要控制器中。出于这个原因,你得用
DispatchesJobs trait
到其它你要以使中调用分发任务的类吃,这样您就是好以斯看似吃运用
dispatch 方法,下面让起一个简约的施用 trait 的言传身教:

<?php

namespace App;

use Illuminate\Foundation\Bus\DispatchesJobs;

class ExampleClass
{
  use DispatchesJobs;
}

dispatch 方法

还是,你可以采用 dispatch 全局帮助方法:

Route::get('/job', function () {
  dispatch(new App\Jobs\PerformTask); 

  return 'Done!';
});

对职责指定队列

乃吗可以指定任务需要被分配至之序列。

您得对君的班任务拓展归类,来以任务推送到不同的队中,你甚至是得分配各种队列工作的优先权。这并无是推送任务到队配置文件被所定义的差之行连接上,而是仅在么连接着指定的班进行的操作。你得以任务实例的
onQueue 方法来指定队列。onQueue 来自 Illuminate\Bus\Queueable
trait,该性状已经给 App\Jobs\Job 基类所引入:

<?php

namespace App\Http\Controllers;

use App\User;

use Illuminate\Http\Request;
use App\Jobs\SendReminderEmail;
use App\Http\Controllers\Controller;

class UserController extends Controller
{
  /**
   * Send a reminder e-mail to a given user.
   *
   * @param Request $request
   * @param int $id
   * @return Response
   */
  public function sendReminderEmail(Request $request, $id)
  {
    $user = User::findOrFail($id);

    $job = (new SendReminderEmail($user))->onQueue('emails');

    $this->dispatch($job);
  }
}

行监控器守护进程

queue:work Artisan 命令包含了一个 --daemon
选项来逼队列工作持续的履行任务要无重复引导框架。这相较 queue:lsten
命令来说会明确的回落 CPU 的耗费:

php artisan queue:work connection-name --daemon

php artisan queue:work connection-name --daemon --sleep=3

php artisan queue:work connection-name --daemon --sleep=3 --tries=3

不怕假设你所盼底,queue:work 任务支持与 queue:listen
差不多的选项。你可由此动 php artisan help queue:work
命令来显示可用选项。

对守护进程的编码注意事项

队任务之看护进程不会见于每个任务履行前还引导框架,所以,你该小心在您的任务完成时去掉一些比较还之资源消耗。比如,如果你下
GD 类库来拍卖图片,你应当以任务履行就后用 imagedestroy
来将那打内存中开展放飞。

变任务类

默认的,所有的可列执行的天职都深受积存于 app/Jobs 目录下,你得由此
Artisan 命令来蛮成一个新的行列任务:

php artisan make:job SendReminderEmail

欠命令会在 app/Jobs 目录下生成一个新的类。该类会促成
Illuminate\Contracts\Queue\ShouldQueue 接口,该接口表明 laravel
应该用该任务添加到后台的任务队列中,而无是一起执行。

砸任务事件

万一您期望于班任务失败时实行某些操作,你可以 Queue::failing
方法来报一个监听事件。这个事件对经 email 或者
HipChat
通知你的团体提供了一个万分好之机会。比如,你可当 AppServiceProvider
在事件备受附加一个回调:

<?php

namespace App\Providers;

use Queue;
use Illuminate\Queue\Events\JobFailed;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
  /**
   * Bootstrap any application service.
   *
   * @return void
   */
   public function boot()
   {
     Queue::failing(function (JobFailed $event) {
       // $event-connectionName
       // $event->job
       // $event-data
     });
   }

   /**
    * Register the service provider.
    *
    * @return void
    */
    public function register()
    {
      //
    }
}

职责类中之黄方法

卿可以当职责类吃定义一个 failed
方法来拓展更加精细的支配,这允许你当职责出现破产时来执行有指定的动作:

<?php

namespace App\Jobs;

use App\Jobs\Job;
use Illuminate\Contracts\Mail\Mailer;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue;

class SendReminderEmail extends Job implements ShouldQueue
{
  use InteractsWithQueue, SerializesModels;

  /**
   * Execute the job.
   *
   * @param Mailer $mailer
   * @return void
   */
   public function handle(Mailer $mailer)
   {
     //
   }

   /**
    * Handle a job failure.
    *
    * @return void
    */
    public function failed()
    {
      // Called when the job is failing...
    }
}

行先决条件

数据库

假定运用 database
队列驱动,你需要丰富一个多少表来处理队列任务。你得运用 queue:table
Artisan 命令来很成一个迁移表。一旦该搬迁表生成完成,你尽管可以用
migrate 命令来搬迁到数据库被:

php artisan queue:table

php artisan migrate

别队依赖

下面列有了别样队列驱动及其对应的依赖性:

  • Amazon SQS: aws/aws-sdk-php ~3.0
  • Beanstalkd: pda/pheanstalk ~3.0
  • Redis: predis/predis ~1.0