1、ThinkPHP 6
2、Workerman version:3.5.31
3、GatewayWorker
4、PHP version:7.4.9
private function start()
{
$this->startRegister();
$this->startGateWay();
$this->startBusinessWorker();
$this->startTimerWorker();
Worker::runAll();
}
private function startTimerWorker()
{
$Task = new Worker();
$Task->count = 1;
$Task->onWorkerStart = function($task)
{
Timer::add(10, function()
{
(new TimerModel)->scanTimeout();
});
Timer::add(10, function()
{
(new TimerModel)->ExportHistory();
});
};
}
Register 与 GateWay 与 BusinessWorker REDIS工作正常,但是我单独创建 TimerWorker 用来轮询处理一些任务的进程,REDIS会获取到脏数据。
有时候还会出现连接REDIS的异常:
RedisException: read error on connection to 127.0.0.1:6379 in /ThinkPHP6/vendor/topthink/framework/src/think/cache/Driver.php:345
不要在
Worker::runAll();
运行前连redis,Worker::runAll();
运行前执行的代码都是运行在主进程,主进程初始化redis后会被子进程共享,导致数据错乱。连接redis的操作放到onWorkerStart里,这样可以让每个子进程都有属于自己的redis连接,互相不影响。大佬,是否还存在其他可能?因为我的REDIS都是在onWorkerStart之后创建的。
已经解决了,谢谢大佬。问题出在ThinkPHP6 初始化的时候会实例化Think/Log对象,Think/Log对象实例化的时候会根据缓存是Redis,而去实例化Redis,执行完这些底层初始化代码,才跑去走应用代码。
我使用的ThinkPHP6 console commands创建的应用
我确信在
里,REDIS 都是在onWorkerStart里或者之后创建的。
我单独创建的 TimerWorker Worker 业务代码里的REDIS也是在 onWorkerStart 里执行的。
我搜索了好久,答案都是描述不能在onWorkerStart前创建连接资源,可是我检查过并没有这样的代码。
是否THINKPHP6的底层,在console 应用 初始化前就连接了缓存了呢?
用原生redis扩展试下吧