日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

关于 Laravel Redis 多个进程同时取队列问题详解

發布時間:2024/9/20 数据库 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 关于 Laravel Redis 多个进程同时取队列问题详解 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這篇文章主要給大家介紹了關于 Laravel Redis 多個進程同時取隊列問題的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或工作具有一定的參考學習價值,需要的朋友下面來一起學習學習吧。

前言

最近在工作中遇到了一個問題,開啟多個進程處理隊列會重復讀取 Redis 中隊列嗎?是否因此導致重復執行任務?下面就來通過示例代碼詳細介紹下。

使用 Supervisor 監聽 Laravel 隊列任務,其中 Supervisor 的配置如下:

?
1 2 3 4 5 6 7 8 [program:laravel-worker] process_name=%(program_name)s_%(process_num)02d command=php /var/www/xxx.cn/artisan queue:work --queue=sendfile --tries=3 --daemon autostart=true autorestart=true numprocs=8 redirect_stderr=true stdout_logfile=/var/www/xxx.cn/worker.log

注意: numprocs = 8,代表開啟 8 個進程來執行 command 中的命令。

如下:

?
1 2 3 4 5 6 7 8 9 10 11 PS C:\Users\tanteng\website\laradock> docker-compose exec php-worker sh /etc/supervisor/conf.d # ps -ef | grep php ?7 root? 0:00 php /var/www/xxx.cn/artisan queue:work --queue=sendfile --tries=3 --daemon ?8 root? 0:00 php /var/www/xxx.cn/artisan queue:work --queue=sendfile --tries=3 --daemon ?9 root? 0:00 php /var/www/xxx.cn/artisan queue:work --queue=sendfile --tries=3 --daemon ?10 root? 0:00 php /var/www/xxx.cn/artisan queue:work --queue=sendfile --tries=3 --daemon ?11 root? 0:00 php /var/www/xxx.cn/artisan queue:work --queue=sendfile --tries=3 --daemon ?12 root? 0:00 php /var/www/xxx.cn/artisan queue:work --queue=sendfile --tries=3 --daemon ?13 root? 0:00 php /var/www/xxx.cn/artisan queue:work --queue=sendfile --tries=3 --daemon ?14 root? 0:00 php /var/www/xxx.cn/artisan queue:work --queue=sendfile --tries=3 --daemon ?44 root? 0:00 grep php

Laravel 多進程讀取隊列內容是否會重復

在 Laravel 的某個控制器方法,一次放入多個任務隊列:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 public function index(Request $request) { ?$this->dispatch((new SendFile3())->onQueue('sendfile')); ?$this->dispatch((new SendFile3())->onQueue('sendfile')); ?$this->dispatch((new SendFile3())->onQueue('sendfile')); ?$this->dispatch((new SendFile3())->onQueue('sendfile')); ?$this->dispatch((new SendFile3())->onQueue('sendfile')); ?$this->dispatch((new SendFile3())->onQueue('sendfile')); ?$this->dispatch((new SendFile3())->onQueue('sendfile')); ?$this->dispatch((new SendFile3())->onQueue('sendfile')); ?$this->dispatch((new SendFile3())->onQueue('sendfile')); ?$this->dispatch((new SendFile3())->onQueue('sendfile')); ?$this->dispatch((new SendFile3())->onQueue('sendfile')); ?$this->dispatch((new SendFile3())->onQueue('sendfile')); ?$this->dispatch((new SendFile3())->onQueue('sendfile')); ?$this->dispatch((new SendFile3())->onQueue('sendfile')); ?$this->dispatch((new SendFile3())->onQueue('sendfile')); ?$this->dispatch((new SendFile3())->onQueue('sendfile')); ?$this->dispatch((new SendFile3())->onQueue('sendfile')); ?$this->dispatch((new SendFile3())->onQueue('sendfile')); }

在隊列處理的方法打印日志,打印處理的隊列的 ID:

app/Jobs/SendFile3.php

?
1 2 3 4 5 6 7 8 public function handle() { ?info('invoke SendFile3'); ?dump('invoke handle'); ?$rawbody = $this->job->getRawBody(); ?$info = json_decode($rawbody, true); ?info('queue id:' . $info['id']); }

Laravel 使用 Redis 的 list 作為隊列的數據結構,并會為每個隊列分配一個 ID,數據結構如下:

?
1 2 3 4 5 6 7 8 9 { ?"job": "Illuminate\\Queue\\CallQueuedHandler@call", ?"data": { ?"commandName": "App\\Jobs\\SendFile3", ?"command": "O:18:\"App\\Jobs\\SendFile3\":4:{s:6:\"\u0000*\u0000job\";N;s:10:\"connection\";N;s:5:\"queue\";s:8:\"sendfile\";s:5:\"delay\";N;}" ?}, ?"id": "hadBcy3IpNsnOofQQdHohsa451OkQs88", ?"attempts": 1 }

請求這個控制器路由(或者命令行方式),就可以看到 Redis 中多了很多隊列任務了,如圖:

這個時候開啟 Supervisor 處理隊列任務,并查看日志:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:JaClJzhDEvntzLCRIz6uRQkCVLbE8Y9C [2017-12-23 19:01:01] local.INFO: queue id:ukHv0Li4P2VgPa55qU6yEOJM27Mo5YwJ [2017-12-23 19:01:01] local.INFO: queue id:ObMpwDTmnaveBUkU7aan5abt3Agyt90l [2017-12-23 19:01:01] local.INFO: queue id:fo2qZn2ftSdQtdnKOciMK7iJb4qlhRGE [2017-12-23 19:01:01] local.INFO: queue id:uLjFMoOU7Wk7bOAd4zpHb3ccRMJHBtR6 [2017-12-23 19:01:01] local.INFO: queue id:87ULqPBObFmGr16nl5wxFVOi71zGCeRM [2017-12-23 19:01:01] local.INFO: queue id:9UVl0muQLzBqlRI99rChGW2ElXwVEMIE [2017-12-23 19:01:01] local.INFO: queue id:a0vgyZuz9HtmH7DGHEpXqesFTcQU3QAF [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:2cXuXxopPkgYiV4WO8gv9CJ6CwXeKtYL [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:9acTAYa8cxpJX6Q3Gb1sULokotP8reqZ [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:BPHQvBboChlv4gr2I0vyLVyw9bijtTYJ [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:Fm6tNajdxYKtdQbDMYDmwWJFLnNikRyg [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:nyAbcvSkBVPbaH3e2ItQkoLJlP1ficib [2017-12-23 19:01:01] local.INFO: queue id:WBHsSVZtP43569UoPXxfLLJcvYmPW7cP [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:bliPnKcRSDApwVmKLNxEhaKelhm0RDEY [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:eOAoQucEIwRz9uZ64xm6IDKgiqj9Xc3W [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:lzise9EiqQqINrhALbmAI4qNg7qylpb2 [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:WXYKvcfOhS1pPnwOwUTsenoMv5l5EUXe [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:XtH5JiwLgnrwWzI02Oyi70pihAOkuJUD [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:9ehmE5HImlpNubpY0xWN8UVrOzxeMqws [2017-12-23 19:01:01] local.INFO: queue id:C1sK87cpZl47edLA0zhfo7PJ9MIEcoyx [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:2kwl51oH4lyyRrljCReGUCkNiJRDl7oe [2017-12-23 19:01:01] local.INFO: queue id:ObRpoqrYTPYiyv2delMlOXu3sAPpWJlN [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:6qgu6W3TapLjSrt688yv9HRXvDDLxntz [2017-12-23 19:01:01] local.INFO: queue id:wiTlERhwn7s9cQkfUF9lLlNADpXjKncI [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:ZSLW0VLFBDpL4wjTJzu3Yb3V45pNe807 [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:qhZlXLGfGWRluIeNm7VbllmTJZYb2h5n [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:LUx1IByD3L2psNl9BZwHhk2knXyRPzW6 [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:M2RESPjyo5hpAFxxL0EQbWwsUq4jpmWn [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:hUsGaiIAOO6ZfGQc5kGHGpsv5RpoRPYO [2017-12-23 19:01:01] local.INFO: queue id:cEHJsOy6bLeZ4NbncPziaHqlarMeyyEF [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:w4bkFiJKMU5saqG2xKN3ZRL5BYXGATMk [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:0zBuwbxlrEhhxKfYBkVyTY4z35f154sI [2017-12-23 19:01:01] local.INFO: queue id:mvoZvyDPvq4tcPjEy9G7PMtH3MwPkPik [2017-12-23 19:01:01] local.INFO: invoke SendFile3 [2017-12-23 19:01:01] local.INFO: queue id:TLvF74eeidECWKtjZqWvW03UJTRPTL9r [2017-12-23 19:01:01] local.INFO: queue id:me8wyPfgcz0nf9xvcXz0hf2xVxqa1FFS

這 8 個進程并發處理隊列,但從打印的日志看,沒有出現同樣的 ID. 我們再看一下 Laravel 如何使用 Redis 處理隊列的。

分析一下 Laravel 隊列的處理

Laravel 中入隊列方法

?
1 2 3 4 5 6 public function pushRaw($payload, $queue = null, array $options = []) { ?$this->getConnection()->rpush($this->getQueue($queue), $payload); ?? ?return Arr::get(json_decode($payload, true), 'id'); }

用的是 Redis 的 rpush 命令。

Laravel 中取隊列方法

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 public function pop($queue = null) { ?$original = $queue ?: $this->default; ?$queue = $this->getQueue($queue); ?$this->migrateExpiredJobs($queue.':delayed', $queue); ?if (! is_null($this->expire)) { ??$this->migrateExpiredJobs($queue.':reserved', $queue); ?} ?list($job, $reserved) = $this->getConnection()->eval( ??LuaScripts::pop(), 2, $queue, $queue.':reserved', $this->getTime() + $this->expire ?); ?if ($reserved) { ??return new RedisJob($this->container, $this, $job, $reserved, $original); ?} }

這里用的是 lua 腳本取隊列,如下:

?
1 2 3 4 5 6 7 8 9 10 11 12 13 14 public static function pop() { ?return <<<'LUA' local job = redis.call('lpop', KEYS[1]) local reserved = false if(job ~= false) then reserved = cjson.decode(job) reserved['attempts'] = reserved['attempts'] + 1 reserved = cjson.encode(reserved) redis.call('zadd', KEYS[2], ARGV[1], reserved) end return {job, reserved} LUA; }

那么結論是:從 Laravel 的處理方式和打印的日志結果看,即使多個進程讀取同一個隊列,也不會讀取到一樣的數據。

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

原文鏈接:https://blog.tanteng.me/2017/12/laravel-supervisor-queue/

來源:http://www.jb51.net/article/131419.htm

總結

以上是生活随笔為你收集整理的关于 Laravel Redis 多个进程同时取队列问题详解的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。