你的位置:首页 > 信息动态 > 新闻中心
信息动态
联系我们

ThinkPHP的MongoDB集群配置方法

2021-12-2 4:14:18

问题

ThinkPHP中对数据库的写入操作强制使用事务,而MongoDB在单机模式下是不支持事务的,需要使用集群才能支持事务,而分布式也是MongoDB的一个特性。所以在实际应用中,MongoDB总是以集群方式搭建的。但ThinkPHP手册总是以MySQL为例,没有详细介绍其他数据库的配置方式,所以还得从源码入手。

ThinkPHP对MongoDB的配置

ThinkPHP6中用于连接MongoDB的ORM是think-orm,具体文件查看
https://github.com/top-think/think-orm/blob/2.0/src/db/connector/Mongo.php
初始化函数:initConnect

    /**
     * 初始化数据库连接
     * @access protected
     * @param boolean $master 是否主服务器
     * @return void
     */
    protected function initConnect(bool $master = true): void
    {
        if (!empty($this->config['deploy'])) {
            // 采用分布式数据库
            if ($master) {
                if (!$this->linkWrite) {
                    $this->linkWrite = $this->multiConnect(true);
                }

                $this->mongo = $this->linkWrite;
            } else {
                if (!$this->linkRead) {
                    $this->linkRead = $this->multiConnect(false);
                }

                $this->mongo = $this->linkRead;
            }
        } elseif (!$this->mongo) {
            // 默认单数据库
            $this->mongo = $this->connect();
        }
    }

无论是否指定了deploy等相关参数,流程最终都会走到这里:https://github.com/top-think/think-orm/blob/2.0/src/db/connector/Mongo.php#L167

if (empty($config['dsn'])) {
    $config['dsn'] = 'mongodb://' . ($config['username'] ? "{$config['username']}" : '') . ($config['password'] ? ":{$config['password']}@" : '') . $config['hostname'] . ($config['hostport'] ? ":{$config['hostport']}" : '');
}

$startTime = microtime(true);

$this->links[$linkNum] = new Manager($config['dsn'], $config['params']);
...

最终都将拼接到dsn字段中去,所以在配置文件中有两种写法

方式一

纯粹的字符串,只写dsnparams参数即可

'type' => 'mongo',
'dsn' => 'mongodb://root:123456@127.0.0.1:27017,127.0.0.1:27018',
'params' => ['authSource' => 'admin'],
'database' => 'test',
 ...

方式二

让ORM去拼接,将usernamepasswordhostname分开填写

'type' => 'mongo',
'hostname' => '127.0.0.1:27017,127.0.0.1:27018',
'params' => ['authSource' => 'admin'],
'database' => 'test',
'username' => 'root',
'password' => '123456',
...

个人推荐第一种URI方式,简单直接。
上面的例子等同于mongodb://root:123456@127.0.0.1:27017,127.0.0.1:27018/?authSource=admin

结论

不要被ThinkPHP的手册“迷惑”了,我们不需要理会deployrw_separate等参数。手册中提及的“分布式”、“读写分离”等名词和MongoDB的集群不是一个东西。

参考

分布式数据库
https://www.php.net/manual/en/mongodb-driver-manager.construct.php