Thinkphp est un framework grand public en Chine, et je pense que de nombreuses personnes doivent l'utiliser. Aujourd'hui, nous allons voir comment se connecter à une base de données distribuée dans Thinkphp.
Bien sûr, nous ne sommes pas là pour expliquer comment utiliser le modèle pour ajouter, supprimer, modifier et interroger la base de données. Nous effectuons une analyse de son code de connexion sous-jacent, ce qui peut vous aider à mieux comprendre le fonctionnement de la base de données par thinkphp. Pour faciliter notre utilisation future.
1. Connexion à une seule base de données
Lorsqu'elle est utilisée, la configuration de la connexion d'une seule base de données est très simple. Il nous suffit de configurer certaines informations dans le fichier de configuration.
'DB_TYPE' => 'mysql', 'DB_HOST' => '192.168.5.102', 'DB_NAME' => 'databasename', 'DB_USER' => 'user', 'DB_PWD' => 'password', 'DB_PORT' => '3306', 'DB_PREFIX' => 'onmpw_',
Vous pouvez l'utiliser une fois le réglage terminé. La valeur par défaut est une connexion à une seule base de données.
2. Connexion à la base de données distribuée
La connexion à une seule base de données est très simple. Concentrons-nous sur l'analyse de la connexion à la base de données distribuée.
'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' => '', // 指定从服务器序号
Suivez la configuration ci-dessus pour vous connecter à la base de données distribuée.
Regardons les options suivantes
'DB_HOST'
Pour les bases de données distribuées, s'il y a plusieurs serveurs, vous devez renseigner plusieurs adresses de serveur, et utiliser séparées par virgules. S'il s'agit d'une distribution maître-esclave, l'adresse précédente doit être l'adresse de la base de données maître.
Pour les noms d'utilisateur, mots de passe, ports d'écoute, etc. suivants, bien sûr, notez-en autant que vous en avez. Si le nom d'utilisateur et le mot de passe de chaque base de données sont identiques, vous ne pouvez en écrire qu'un seul.
Le code pour analyser ces options est le suivant
$_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 signifie distribué, 0 signifie centralisé (c'est-à-dire un seul serveur).
L'implémentation de cette option est dans la classe ThinkDbDirver
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'] représente l'option de configuration 'DB_DEPLOY_TYPE' La configuration ci-dessus est utilisée pour All. ont déjà été analysés et les éléments de configuration se trouvent tous dans le tableau $this->config. Quant à la façon d'analyser le fichier de configuration, nous ne le présenterons pas ici. Ceux qui sont intéressés peuvent se référer à la classe ThinkDb.
La fonction $this->multiConnect() est utilisée pour la connexion distribuée. Si l'option 'DB_DEPLOY_TYPE' est définie sur 1, cette fonction sera exécutée. Sinon, exécutez directement la fonction $this->connect().
‘DB_RW_SEPARATE’=>true
vrai signifie que la lecture et l'écriture sont séparées ; faux signifie que la lecture et l'écriture ne sont pas séparées.
Il convient de noter ici que la séparation de la lecture et de l'écriture repose sur le système de base de données maître-esclave. Lorsque cette option est définie sur true, la base de données maître écrit et la base de données esclave lit.
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'] utilise la séparation en lecture et en écriture lorsqu'elle est vraie, et ne sépare pas la lecture et l'écriture lorsqu'elle est fausse. Pourquoi la séparation entre lecture et écriture doit-elle être maître-esclave ? Étant donné que le serveur esclave ne peut pas écrire et ne peut que lire, si des données sont écrites sur le serveur esclave, elles ne peuvent pas être synchronisées. Cela entraînera une incohérence des données. Par conséquent, si notre système est maître-esclave, nous devons utiliser la séparation lecture-écriture. En d'autres termes, l'option DB_RW_SEPARATE doit être configurée comme vraie.
'DB_MASTER_NUM'=>1
Le chiffre après cette option indique le nombre de serveurs principaux après séparation en lecture et en écriture. Par conséquent, cette option est également utilisée dans les systèmes de bases de données maître-esclave.
Le code suivant sélectionne le serveur principal.
$m = floor(mt_rand(0,$this->config['master_num']-1));
Lors de la lecture depuis la base de données maître-esclave, sélectionnez le code principal à lire depuis le serveur esclave
$r = floor(mt_rand($this->config['master_num'],count($_config['hostname'])-1)); // 每次随机连接的数据库
où $this->config['master_num'] représente le nombre de serveurs maîtres.
'DB_SLAVE_NO'=> ''
Spécifiez le numéro de série du serveur esclave pour la lecture des données. S'il n'est pas défini, le nombre de serveurs esclaves sera calculé en fonction du nombre de serveurs maîtres, puis un sera sélectionné au hasard pour la lecture.
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)); // 每次随机连接的数据库 }
Ce qui précède est une explication simple du code d'implémentation de la fonction de chaque option.
Jetons un coup d'œil à la partie connexion
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);
Voyant cela, je pense que tout le monde devrait être conscient du $r et du $m lors de l'introduction du code pour chaque option de configuration ci-dessus. est-ce que ça fait ?
Regardons maintenant $r == $m ? false : $db_master si la lecture et l'écriture de la base de données ne sont pas séparées et que la lecture et l'écriture sont un serveur, la valeur transmise à la fonction de connexion est fausse. . Ou si l'écriture maître-esclave est séparée, la valeur transmise pour se connecter est également fausse. D'après le code ci-dessus, nous voyons que si $r et $m ne sont pas égaux, $db_master sera défini. En fait, cela équivaut à une sauvegarde. Si le serveur $r sélectionné tombe en panne et ne peut pas être connecté, il se connectera à $db_master.
Le troisième paramètre de la fonction connect() indique en fait s'il faut choisir une connexion de secours lorsque la connexion au serveur $db_config échoue. False signifie pas de reconnexion, d'autres valeurs signifient une reconnexion.
Le code de base est le suivant
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()); } }
De cette façon, pour le type maître-esclave, $r et $m ne seront certainement pas les mêmes. Par conséquent, si le serveur esclave sélectionné échoue lors de la lecture des données, le serveur maître servira de sauvegarde et ira éventuellement vers le serveur maître pour les lire. Il peut garantir la rapidité de la lecture des données.
Cependant, j'ai toujours l'impression que ce n'est pas encore parfait. S'il existe plusieurs serveurs esclaves et que le serveur esclave et le serveur maître sélectionnés lors de la lecture échouent, la lecture des données échouera. À l'heure actuelle, il devrait être plus sécurisé si d'autres serveurs esclaves peuvent être à nouveau lus. Bien entendu, les fonctions actuelles de thinkphp sont assez complètes et suffisantes pour notre usage. Mais j'espère toujours que thinkphp deviendra de plus en plus parfait à l'avenir.
J'espère que l'introduction ci-dessus pourra être utile à tout le monde lors de l'utilisation de thinkphp pour le développement.
Recommandations associées :
Partage de code de mise en cache de fichiers ThinkPHP
Évaluation des performances de la base de données et du modèle de ThinkPHP
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!