× 警告!旧版文档已经暂停维护,请查看新版文档。点击前往新版文档

是否可以共用1个redis或mysql连接

绝对不可以。必须每个进程单独创建RedisMySQLPDO连接,其他的存储客户端同样也是如此。原因是如果共用1个连接,那么返回的结果无法保证被哪个进程处理。持有连接的进程理论上都可以对这个连接进行读写,这样数据就发生错乱了。

所以在多个进程之间,一定不能共用连接

  • swoole_server中,应当在onWorkerStart中创建连接对象
  • swoole_process中,应当在swoole_process->start后,子进程的回调函数中创建连接对象
  • 本页面所述信息对使用pcntl_fork的程序同样有效

示例

$serv = new swoole_server("0.0.0.0", 9502);

//必须在onWorkerStart回调中创建redis/mysql连接
$serv->on('workerstart', function($serv, $id) {
    $redis = new redis;
    $redis->connect('127.0.0.1', 6379);
    $serv->redis = $redis;
});

$serv->on('receive', function (swoole_server $serv, $fd, $from_id, $data) { 
    $value = $serv->redis->get("key");
    $serv->send($fd, "Swoole: ".$value);
});

$serv->start();

  • lion

    onWorkerStart中建立redis对象后,在task回调函数中怎么使用啊?

  • swooler

    task进程也是worker进程的一种,上面的案例中给每个worker进程分配一个redis链接并保存到了serv对象中,你在ontask回调函数中,参数第一个就是serv,和worker一样,直接在函数体内进行调用就可以了.

  • 王南

    $serv变量是在onWorkStart回调之前定义的,应该属于程序全局期作用域对象,程序全局对象所用的内存是所有work进程共享的,那么我有个疑问,在onWorkStart回调里面给$serv->redis赋值,为什么多个进程就能区分开自己进程内的redis呢,而不是被最后创建的那个work进程覆盖掉$serv->redis属性呢?

  • 王南

    程序全局期 http://wiki.swoole.com/wiki/page/354.html 按照上面手册地址,$serv是在在swoole_server->start之前就创建好的对象,应该属于程序全局期 而且由于swoole是多进程的,所以程序全局对象在代码中仅是可读的,这里怎么可以写了?

  • 生活不能自理

    workerstart可以创建多个,不会被覆盖

  • haozy

    workerstart相当于pcntl_fork的子进程了

  • Smˋ﹎ 哟、

    在work中创建的tick进程能和work共用一个连接吗

  • dawn

    文件读写冲突怎么处理,我用了flock依然无效。

  • U
    U

    在onworkerstart内需要使用单例吗?

  • ee

    大佬,在一个会话周期内 也是不可以的吧?

  • !

    swoole混合协议使用,每次都会进入workerstart,并且在workerstart里面创建的redis或者mysql,在http的request里面获取不到,request里面的代码执行完之后,再执行workerstart

  • 时光易逝。

    投递异步任务是,MySQL连接断开,在workerstart怎样进行断线重连?还是在task里创建连接,断线重连?

  • 清风

    程序全局期作用域对象,这部分内存会在写时分离(COW),在Worker进程内对这些对象进行写操作时,会自动从共享内存中分离,变为进程全局对象。

  • 火端

    感觉这个示例是错的,如果有多个worker,最后一个会把$serv->redis覆盖

  • 18717991602

    然而并不会,我在onworkerstart 方法内,通过区分workerid来构建不同的redis库,然后在connect方法内去写入redis,发现所有写入并不会只在一个库内

    public function WorkerStart(\Swoole\Server $server, int $worker_id)
        {
            $this->_serv = $server;
    
            //初始化Redis服务
            if ($worker_id == 0)   $this->_serv->redis = Redis::connection('default');
            if ($worker_id == 1)   $this->_serv->redis = Redis::connection('cache');
        }