This article mainly introduces the ThinkPHP framework distributed database connection method, and analyzes the thinkPHP framework's distributed database connection method, operation skills and related precautions in detail in the form of examples. Friends in need can refer to the following
This article analyzes the ThinkPHP framework distributed database connection method through examples. Share it with everyone for your reference, the details are as follows:
Thinkphp is a popular framework in China, and I believe there must be many people using it. In this article, we will analyze an important part of Thinkphp - the connection of distributed databases.
Of course, we are not here to explain how to use the model to add, delete, modify, and query the database. We are doing an analysis of its underlying connection code, which can help you better understand thinkphp's operation of the database. To facilitate our future use.
1. Single database connection
When used, the connection configuration of a single database is very simple. We only need to configure some information in the configuration file.
'DB_TYPE' => 'mysql', 'DB_HOST' => '192.168.5.102', 'DB_NAME' => 'databasename', 'DB_USER' => 'user', 'DB_PWD' => 'password', 'DB_PORT' => '3306', 'DB_PREFIX' => 'onmpw_',
It can be used after the setting is completed. The default is a single database connection.
2. Distributed database connection
The connection to a single database is very simple. Let’s focus on analyzing the connection to the distributed database.
'DB_TYPE' => 'mysql', 'DB_HOST' => '192.168.5.191,192.168.5.88,192.168.5.103', 'DB_NAME' => 'test,test,test', 'DB_USER' => 'masteruser,slaveuser,slaveuser', 'DB_PWD' => 'masterpass,slavepass,slavepass', 'DB_PORT' => '3306', 'DB_PREFIX' => '', 'DB_DEPLOY_TYPE' => 1, // 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器) 'DB_RW_SEPARATE' => true, // 数据库读写是否分离 主从式有效 'DB_MASTER_NUM' => 1, // 读写分离后 主服务器数量 'DB_SLAVE_NO' => '', // 指定从服务器序号
Follow the above configuration to connect to the distributed database.
Let’s look at the following options
'DB_HOST'
Distributed database requires several servers Fill in several server addresses, separating each address with commas. If it is a master-slave distribution, the previous address must be the address of the master database.
For the following user names, passwords, listening ports, etc., of course, write down as many as you have. If the username and password of each database are the same, you can only write one.
The code for parsing these options is as follows
$_config['username'] = explode(',',$this->config['username']); $_config['password'] = explode(',',$this->config['password']); $_config['hostname'] = explode(',',$this->config['hostname']); $_config['hostport'] = explode(',',$this->config['hostport']); $_config['database'] = explode(',',$this->config['database']); $_config['dsn'] = explode(',',$this->config['dsn']); $_config['charset'] = explode(',',$this->config['charset']);
'DB_DEPLOY_TYPE'=>1
1 means distribution formula, 0 represents centralized (that is, a single server).
The implementation of this option is in the class Think\Db\Dirver
protected function initConnect($master=true) { if(!empty($this->config['deploy'])) // 采用分布式数据库 $this->_linkID = $this->multiConnect($master); else // 默认单数据库 if ( !$this->_linkID ) $this->_linkID = $this->connect(); }
$this->config['deploy']
means that is 'DB_DEPLOY_TYPE'
For this configuration option, the above configuration has been parsed before use, and the configuration items are all in the $this->config
array. As for how to parse the configuration file, we will not introduce it here. Those who are interested can refer to the Think\Db class.
$this->multiConnect()
The function is used for distributed connections. If the 'DB_DEPLOY_TYPE'
option is set to 1, this function will be executed. . Otherwise, execute the $this->connect()
function directly.
'DB_RW_SEPARATE'=>true
true means reading and writing are separated; false means reading and writing are not separated.
It should be noted here that the separation of reading and writing is based on the master-slave database system. When this option is set to true, the master database writes and the slave database reads.
if($this->config['rw_separate']){ // 主从式采用读写分离 if($master) // 主服务器写入 $r = $m; else{ if(is_numeric($this->config['slave_no'])) {// 指定服务器读 $r = $this->config['slave_no']; }else{ // 读操作连接从服务器 $r = floor(mt_rand($this->config['master_num'],count($_config['hostname'])-1)); // 每次随机连接的数据库 } } }else{ // 读写操作不区分服务器 $r = floor(mt_rand(0,count($_config['hostname'])-1)); // 每次随机连接的数据库 }
$this->config['rw_separate']
When it is true, reading and writing are separated. When it is false, reading and writing are not separated. Why does the separation of reading and writing have to be master-slave? Because the slave server cannot write and can only read, if data is written to the slave server, the data cannot be synchronized. This will cause data inconsistency. Therefore, if our system is master-slave, we must use read-write separation. In other words, the DB_RW_SEPARATE option must be configured as true.
'DB_MASTER_NUM'=>1
The number after this option indicates the number of master servers after read and write separation. Therefore this option is also used in master-slave database systems.
The following code selects the main server.
$m = floor(mt_rand(0,$this->config['master_num']-1));
When reading from the master-slave database, select the core code to read from the server
Copy code The code is as follows:
$r = floor(mt_rand($this->config['master_num'],count($_config['hostname'])-1)); // 每次随机连接的数据库
Among them $this->config['master_num']
Indicates the number of master servers.
'DB_SLAVE_NO'=> ''
Specifies the serial number of the slave server for reading data. If not set, the number of slave servers will be calculated based on the number of master servers, and then one will be randomly selected for reading.
if(is_numeric($this->config['slave_no'])) {// 指定服务器读 $r = $this->config['slave_no']; }else{ // 读操作连接从服务器 $r = floor(mt_rand($this->config['master_num'],count($_config['hostname'])-1)); // 每次随机连接的数据库 }
The above is a simple explanation of the implementation code of the role of each option.
Let’s take a look at the connection part
if($m != $r ){ $db_master = array( 'username' => isset($_config['username'][$m])?$_config['username'][$m]:$_config['username'][0], 'password' => isset($_config['password'][$m])?$_config['password'][$m]:$_config['password'][0], 'hostname' => isset($_config['hostname'][$m])?$_config['hostname'][$m]:$_config['hostname'][0], 'hostport' => isset($_config['hostport'][$m])?$_config['hostport'][$m]:$_config['hostport'][0], 'database' => isset($_config['database'][$m])?$_config['database'][$m]:$_config['database'][0], 'dsn' => isset($_config['dsn'][$m])?$_config['dsn'][$m]:$_config['dsn'][0], 'charset' => isset($_config['charset'][$m])?$_config['charset'][$m]:$_config['charset'][0], ); } $db_config = array( 'username' => isset($_config['username'][$r])?$_config['username'][$r]:$_config['username'][0], 'password' => isset($_config['password'][$r])?$_config['password'][$r]:$_config['password'][0], 'hostname' => isset($_config['hostname'][$r])?$_config['hostname'][$r]:$_config['hostname'][0], 'hostport' => isset($_config['hostport'][$r])?$_config['hostport'][$r]:$_config['hostport'][0], 'database' => isset($_config['database'][$r])?$_config['database'][$r]:$_config['database'][0], 'dsn' => isset($_config['dsn'][$r])?$_config['dsn'][$r]:$_config['dsn'][0], 'charset' => isset($_config['charset'][$r])?$_config['charset'][$r]:$_config['charset'][0], ); return $this->connect($db_config,$r,$r == $m ? false : $db_master);
Seeing this, I think everyone should understand the role of $r and $m when introducing the code for each configuration option above. .
现在我们来看 $r == $m ? false : $db_master ,如果数据库读写不分离的情况下,读写是一台服务器的话 传给connect函数的值为false。或者是如果是主从分离的写的情况下传给connect的值也为false。通过上面代码我们看到,如果$r和$m不相等的情况下,会设置$db_master。其实也就是相当于一台备用的,如果选择的$r服务器出现故障不能连接,将会去连接$db_master。
connect()函数的第三个参数其实是表示当$db_config这台服务器连接故障时是否选择备用的连接。false表示不重连,其它值即表示重新连接。
其核心代码如下
try{ if(empty($config['dsn'])) { $config['dsn'] = $this->parseDsn($config); } if(version_compare(PHP_VERSION,'5.3.6','<=')){ // 禁用模拟预处理语句 $this->options[PDO::ATTR_EMULATE_PREPARES] = false; } $this->linkID[$linkNum] = new PDO( $config['dsn'], $config['username'], $config['password'],$this->options); }catch (\PDOException $e) { if($autoConnection){ //$autoConnection不为false,而是默认的主服务器 trace($e->getMessage(),'','ERR'); return $this->connect($autoConnection,$linkNum); //出现异常,使用递归函数重新连接 }elseif($config['debug']){ E($e->getMessage()); } }
这种方式,对于主从式来说,$r和$m肯定不会相同。因此如果说在读取数据的时候,选择的那台从服务器出现故障的话,那主服务器即是备用的,最后会去主服务器读取。能保证数据读取的时效性。
但是,总感觉现在还不太完善。如果说有多台从服务器,在读取的时候选择的那台从服务器和主服务器都出现了故障,那数据岂不是就读取失败了。这时候如果能再次读取其它的从服务器的话那应该是更有保障。当然了,目前的thinkphp的功能已经相当完善,足够我们使用了。但是还是希望thinkphp以后越来越完善。
相关推荐:
The above is the detailed content of Detailed explanation of distributed database connection method of ThinkPHP framework. For more information, please follow other related articles on the PHP Chinese website!