Redis消息隊列組件 redis-queue 大批量失敗
問題出現場景:
一次性插入20000條消費信息 , 消息隊列 進程100 , 隊列處理接近8000-10000 的條數的時候 , 就會出現報錯
錯誤如下:
/data/web/webman/vendor/workerman/redis/src/Client.php:305
Stack trace:
#0 /data/web/webman/vendor/workerman/workerman/Events/Select.php(232): Workerman\Redis\Client->Workerman\Redis\{closure}()
#1 /data/web/webman/vendor/workerman/workerman/Events/Select.php(281): Workerman\Events\Select->tick()
#2 /data/web/webman/vendor/workerman/workerman/Worker.php(2430): Workerman\Events\Select->loop()
#3 /data/web/webman/vendor/workerman/workerman/Worker.php(1554): Workerman\Worker->run()
#4 /data/web/webman/vendor/workerman/workerman/Worker.php(1384): Workerman\Worker::forkOneWorkerForLinux(Object(Workerman\Worker))
#5 /data/web/webman/vendor/workerman/workerman/Worker.php(1358): Workerman\Worker::forkWorkersForLinux()
#6 /data/web/webman/vendor/workerman/workerman/Worker.php(542): Workerman\Worker::forkWorkers()
#7 /data/web/webman/start.php(156): Workerman\Worker::runAll()
#8 {main}Workerman\Redis\Exception: Workerman Redis Wait Timeout (10 seconds) in /data/web/webman/vendor/workerman/redis/src/Client.php:305
Stack trace:
#0 /data/web/webman/vendor/workerman/workerman/Events/Select.php(232): Workerman\Redis\Client->Workerman\Redis\{closure}()
#1 /data/web/webman/vendor/workerman/workerman/Events/Select.php(281): Workerman\Events\Select->tick()
#2 /data/web/webman/vendor/workerman/workerman/Worker.php(2430): Workerman\Events\Select->loop()
#3 /data/web/webman/vendor/workerman/workerman/Worker.php(1554): Workerman\Worker->run()
#4 /data/web/webman/vendor/workerman/workerman/Worker.php(1384): Workerman\Worker::forkOneWorkerForLinux(Object(Workerman\Worker))
#5 /data/web/webman/vendor/workerman/workerman/Worker.php(1358): Workerman\Worker::forkWorkersForLinux()
#6 /data/web/webman/vendor/workerman/workerman/Worker.php(542): Workerman\Worker::forkWorkers()
#7 /data/web/webman/start.php(156): Workerman\Worker::runAll()
#8 {main}
redis 性能截圖:
有沒有大佬幫忙給看下問題
workerman/redis 是異步的,當有大量redis請求要發(fā)給redis時,請求會放在進程一個排隊里,然后一個一個發(fā)給redis。
當redis處理不過來時,隊列里的數據會積壓,如果隊列里有請求超過10秒還沒發(fā)送給redis處理,就會報Workerman Redis Wait Timeout (10 seconds)
。
如果消量很大,可以用redis擴展來發(fā)送,它是同步的。參考 http://doc.workerman.net/components/workerman-redis-queue.html 里 在非workerman環(huán)境向隊列發(fā)送消息 部分使用redis擴展發(fā)送隊列消息
通過查看代碼超時時間 設置默認為 10S , 增加了配置文件
'wait_timeout' => 20 //超時20秒
最起碼能解決快速超時 , 但是 插入效率不是改變 , 但是不知道超時 時間過長會不會對程序穩(wěn)定性會不會有影響呢
還有其他方案 , 單批次插入 特定條數 , 比如說 10000 條, 立即重啟下次 計時器 , 會不會是可行的?
以下是隊列插入邏輯源碼:
foreach ($this->_queue as $key => $queue) {
if ($first_queue && $ignore_first_queue) {
$first_queue = false;
continue;
}
if ($time - $queue[1] > $timeout) {
$has_timeout = true;
unset($this->_queue[$key]);
$msg = "Workerman Redis Wait Timeout ($timeout seconds)";
if ($queue[2]) {
$this->_error = $msg;
\call_user_func($queue[2], false, $this);
} else {
echo new Exception($msg);
}
}
}
如果改為:
foreach ($this->_queue as $key => $queue) {
if ($first_queue && $ignore_first_queue) {
$first_queue = false;
continue;
}
if ($time - $queue[1] > $timeout) {
//直接return , 也許需要等下有 Client::send 才能重新激活
return ;
}
}
是否可行 , 還未測試