webman Redis消息队列组件 redis-queue 大批量失败

0

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 性能截图:


有没有大佬帮忙给看下问题

已邀请:

walkor

赞同来自: shixiaofei cai584887013

workerman/redis 是异步的,当有大量redis请求要发给redis时,请求会放在进程一个排队里,然后一个一个发给redis。
当redis处理不过来时,队列里的数据会积压,如果队列里有请求超过10秒还没发送给redis处理,就会报Workerman Redis Wait Timeout (10 seconds)


如果消量很大,可以用redis扩展来发送,它是同步的。参考 http://doc.workerman.net/components/workerman-redis-queue.html 里 在非workerman环境向队列发送消息 部分使用redis扩展发送队列消息

shixiaofei - 搬砖

赞同来自:


通过查看代码超时时间 设置默认为 10S , 增加了配置文件


'wait_timeout' => 20 //超时20秒

最起码能解决快速超时 , 但是 插入效率不是改变 , 但是不知道超时 时间过长会不会对程序稳定性会不会有影响呢


还有其他方案 , 单批次插入 特定条数 , 比如说 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 ;
}
}

是否可行 , 还未测试

要回复问题请先登录注册