Maison > développement back-end > tutoriel php > Explication détaillée de la méthode de connexion à la base de données distribuée du framework ThinkPHP

Explication détaillée de la méthode de connexion à la base de données distribuée du framework ThinkPHP

不言
Libérer: 2023-03-25 10:28:02
original
2344 Les gens l'ont consulté

Cet article présente principalement la méthode de connexion à la base de données distribuée du framework ThinkPHP et analyse en détail la méthode de connexion à la base de données distribuée du framework thinkPHP, les compétences opérationnelles et les précautions associées sous forme d'exemples. Les amis dans le besoin peuvent s'y référer

Cet article analyse la méthode de connexion à la base de données distribuée du framework ThinkPHP à travers des exemples. Partagez-le avec tout le monde pour référence, les détails sont les suivants :

Thinkphp est un framework populaire en Chine, et je pense que de nombreuses personnes doivent l'utiliser. Dans cet article, nous analyserons une partie importante de Thinkphp : la connexion de bases de données distribuées.

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_',
Copier après la connexion
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 à une base de données distribuée

La connexion d'une seule base de données est très simple. Concentrons-nous sur l'analyse de la connexion d'une 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' => '', // 指定从服务器序号
Copier après la connexion
Suivez la configuration ci-dessus pour vous connecter à la base de données distribuée.

Regardons les options suivantes

'DB_HOST'

Une base de données distribuée nécessite plusieurs serveurs Remplissez plusieurs serveurs. adresses, en séparant chaque adresse par des 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']);
Copier après la connexion

'DB_DEPLOY_TYPE'=>1

1 signifie qu'il est distribué et 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();
}
Copier après la connexion

représente l'option de configuration $this->config['deploy'] La configuration ci-dessus a été analysée avant utilisation. le tout dans le tableau 是'DB_DEPLOY_TYPE'. Quant à la manière 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->config

est utilisée pour les connexions distribuées. Si l'option $this->multiConnect() est définie sur 1, cette fonction sera exécutée. Sinon, exécutez directement la fonction 'DB_DEPLOY_TYPE'. $this->connect()

'DB_RW_SEPARATE'=>true

true signifie que la lecture et l'écriture sont séparées ; false 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. Lorsque

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));  // 每次随机连接的数据库
}
Copier après la connexion

est vrai, la lecture et l'écriture sont séparées, et lorsque $this->config['rw_separate']

est vrai, la lecture et l'écriture ne sont pas séparées. 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 maîtres 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.
$m = floor(mt_rand(0,$this->config['master_num']-1));
Copier après la connexion

Le code suivant sélectionne le serveur principal.

Lors de la lecture depuis la base de données maître-esclave, sélectionnez le code principal à lire depuis le serveur

$r = floor(mt_rand($this->config['master_num'],count($_config['hostname'])-1));   // 每次随机连接的数据库
Copier après la connexion
Copiez le code

Le code est le suivant :$this->config['master_num']

représente le nombre de serveurs maîtres.

'DB_SLAVE_NO'=> ''

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));  // 每次随机连接的数据库
}
Copier après la connexion

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.

Ce qui précède est une explication simple du code d'implémentation de la fonction de chaque option.
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);
Copier après la connexion

Jetons un coup d'œil à la partie connexion

<🎜><🎜>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 ? <🎜>

现在我们来看 $r == $m ? false : $db_master ,如果数据库读写不分离的情况下,读写是一台服务器的话 传给connect函数的值为false。或者是如果是主从分离的写的情况下传给connect的值也为false。通过上面代码我们看到,如果$r和$m不相等的情况下,会设置$db_master。其实也就是相当于一台备用的,如果选择的$r服务器出现故障不能连接,将会去连接$db_master。

connect()函数的第三个参数其实是表示当$db_config这台服务器连接故障时是否选择备用的连接。false表示不重连,其它值即表示重新连接。

其核心代码如下

try{
  if(empty($config[&#39;dsn&#39;])) {
   $config[&#39;dsn&#39;] =  $this->parseDsn($config);
  }
  if(version_compare(PHP_VERSION,&#39;5.3.6&#39;,&#39;<=&#39;)){
    // 禁用模拟预处理语句
    $this->options[PDO::ATTR_EMULATE_PREPARES] =  false;
  }
  $this->linkID[$linkNum] = new PDO( $config[&#39;dsn&#39;], $config[&#39;username&#39;], $config[&#39;password&#39;],$this->options);
}catch (\PDOException $e) {
  if($autoConnection){ //$autoConnection不为false,而是默认的主服务器
    trace($e->getMessage(),&#39;&#39;,&#39;ERR&#39;);
      return $this->connect($autoConnection,$linkNum); //出现异常,使用递归函数重新连接
    }elseif($config[&#39;debug&#39;]){
      E($e->getMessage());
  }
}
Copier après la connexion

这种方式,对于主从式来说,$r和$m肯定不会相同。因此如果说在读取数据的时候,选择的那台从服务器出现故障的话,那主服务器即是备用的,最后会去主服务器读取。能保证数据读取的时效性。

但是,总感觉现在还不太完善。如果说有多台从服务器,在读取的时候选择的那台从服务器和主服务器都出现了故障,那数据岂不是就读取失败了。这时候如果能再次读取其它的从服务器的话那应该是更有保障。当然了,目前的thinkphp的功能已经相当完善,足够我们使用了。但是还是希望thinkphp以后越来越完善。

相关推荐:

thinkPHP5.0框架命名空间详解




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!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal