Thinkphp as the domestic mainstream framework, I believe that the use of people must be a minority. Today, let's take a look at how the distributed database is connected in thinkphp.
Of course, we are not here to use the model to make the database to be used for pruning and checking. We do an analysis of the underlying connection code to help you better understand thinkphp's operations on the database. It is convenient for us to use later.
I. Connection to a single database
When used, the connection configuration of a single database is very simple. We only need to configure the 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_ ',
After the setup is complete, you can use it. By default, a single database connection is in progress.
Second, the connection of the distributed database
The connection to a single database is simple, and we focus on the connection of 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 ' and ' = ' 3306 ', ' db_prefix ' = ', ' db_deploy_type ' + 1,//Database deployment method: 0 Centralized (single server), 1 distributed (Master-slave server) ' db_rw_separate ' + true, ///database read/write whether separate master-slave effective ' db_master_num ' and ' = 1 ' ,//read/write separation of the number of the master servers ' db_slave_no ' + ' ,//specify from server ordinal
With the above configuration, you can connect to the distributed database.
Let's look at a few options below
' Db_host '
Distributed database, there are several servers to fill in several server addresses, each address separated by commas. If it is a master-slave distribution, the previous address is the address of the primary database.
For the following user name and password there are listening ports and so on, of course, there are a few to write a few. If the user name and password are the same for each database, you can write only 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
The 1 representation is distributed, and 0 represents a 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 ')) //with distributed database $ This->_linkid = $this->multiconnect ($master); else //default single database if (! $this->_linkid) $this->_linkid = $this->connect ();}
$this->config[' Deploy ' represents the ' db_deploy_type ' configuration option, the above configuration has been parsed before use, and the configuration items are in the $this->config array. As to how to parse the configuration file, here we do not introduce, interested can refer to the Think\db class.
The $this->multiconnect () function is used for distributed connections, and if the ' db_deploy_type ' option is set to 1, the function executes. Otherwise, execute the $this->connect () function directly.
' Db_rw_separate ' =>true
True indicates read-write separation; False indicates that read/write is not separated.
It is important to note that the read-write separation is based on the master-slave database system. This option is set to True when the primary database is written and read from the database.
if ($this->config[' rw_separate ')) { //master-slave with read-write separation if ($master) //Primary server write $r = $m; else{ if (is_numeric ($this->config[' slave_no ')) {//Specify server read $r = $this->config[' slave_no ']; } else{ //read operation connection from server $r = Floor (Mt_rand ($this->config[' Master_num '],count ($_config[' hostname '])-1)); Each randomly connected database } }}else{ //read-write operation does not differentiate between server $r = Floor (Mt_rand (0,count ($_config[' hostname '])-1)); Each randomly connected database}
$this->config[' Rw_separate ') is true when read-write separation is used, and read/write is not separated when false. Why does the read-write separation have to be master-slave? Since the server cannot write to read only, if the data is written to the slave server, the data cannot be synchronized. This can result in inconsistent data. So, if our system is a master-slave, we have to use read-write separation. This means that the Db_rw_separate option must be configured to TRUE.
' Db_master_num ' =>1
The number after this option indicates the number of master servers after read-write separation. Therefore, this option is also used for master-slave database systems.
The following code is to select the primary server.
$m = Floor (mt_rand (0, $this->config[' Master_num ']-1));
Select the core code to read from the server when the master-slave database reads
$r = Floor (Mt_rand ($this->config[' Master_num '],count ($_config[' hostname '])-1); Every random connection to the database
where $this->config[' Master_num ' represents the number of primary servers.
' Db_slave_no ' and ' = '
Specifies the sequence number from the server that is used to read the data. If not set, the number of books from the server is calculated based on the number of primary servers, and then a random selection is made to read from it.
if (Is_numeric ($this->config[' slave_no ')) {//Specify server read $r = $this->config[' slave_no '];} else{ //read operation connection from server $r = Floor (Mt_rand ($this->config[' Master_num '],count ($_config[' hostname '])-1)); Each randomly connected database}
The above is a simple explanation of the implementation code for each option's function.
Let's look at the parts of the connection
if ($m! = $r) {$db _master = array (' username ' = isset ($_config[' username '] [$m])? $_config[' username '] [$m]:$_c onfig[' 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 ($_confi g[' 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);
To see this, I think we should be on the above in the introduction of the various configuration options of the code in which the "and $m is what role."
Now let's see $r = = $m? False: $db _master, if the database read and write is not separated, read and write is a server, the value passed to the Connect function is false. Or if it is a master-slave separate write, the value passed to connect is also false. By the above code we see that if "and $m are not equal, the $db_master will be set." In fact, it is equivalent to a standby, if the selected server fails to connect, will connect to $db_master.
The third parameter of the Connect () function actually indicates whether an alternate connection is selected when the $db_config server fails to connect. False means no reconnection, and other values indicate reconnection.
The core code is as follows
try{ if (Empty ($config [' DSN '])) { $config [' DSN '] = $this->parsedsn ($config); } if (Version_compare (php_version, ' 5.3.6 ', ' <= ')) { //Disable analog preprocessing statements $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 not false, but default primary server trace ($e GetMessage (), ', ' ERR '); return $this->connect ($autoConnection, $linkNum); An exception occurred, using a recursive function to reconnect }elseif ($config [' Debug ']) { E ($e->getmessage ())} }
This way, for the master-slave, $r and $m certainly not the same. Therefore, if the selected server fails when the data is read, the primary server is standby, and the primary server is read. To ensure the timeliness of data read.
But the overall feeling is not perfect yet. If there are multiple slave servers, the one selected from the server and the primary server fails at the time of reading, then the data is not read failed. It should be more secure if you can read the other slave servers again. Of course, the current thinkphp function has been quite perfect, enough for us to use. But still hope thinkphp more perfect after.
I hope the above introduction can be helpful to you when you use thinkphp to develop.
Related recommendations:
ThinkPHP5 Framework basics, development specifications and directory structure
thinkphp file cache class code sharing
thinkphp DB and model performance evaluation