Maison  >  Article  >  développement back-end  >  Explication détaillée de la base de données distribuée thinkphp

Explication détaillée de la base de données distribuée thinkphp

jacklove
jackloveoriginal
2018-06-15 11:36:382413parcourir

1. Qu'est-ce qu'une base de données distribuée :

La base de données distribuée de tp est principalement configurée via cette configuration :

 'DB_DEPLOY_TYPE' =>1,// Méthode de déploiement de la base de données : 0 centralisé (serveur unique), 1 distribué (serveur maître-esclave)

2. Quelle est la séparation lecture-écriture du serveur maître-esclave :

La base de données maître-esclave signifie qu'une base de données maître aura n bases de données esclaves correspondantes, tandis qu'une base de données esclave ne peut avoir qu'une seule base de données esclave correspondante. Les opérations d'écriture dans la base de données maître-esclave nécessitent l'utilisation de la base de données maître, tandis que les opérations de lecture utilisent la base de données esclave. La base de données maître et la base de données esclave maintiennent toujours la cohérence des données. Le principe de maintien de la cohérence de la base de données est que lorsque les données de la base de données principale changent, l'opération sera écrite dans le journal de la base de données principale et la base de données esclave continuera à lire le journal de la base de données principale et à l'enregistrer dans son propre système de journalisation, puis exécutez-le, gardant ainsi la base de données maître-esclave cohérente.

3 Explication détaillée

1. Connexion

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 à 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 de 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 serveurs adresses. Séparez chaque adresse par une virgule. 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.

对于下面的用户名和密码还有监听端口之类的,当然是有几个就写几个。如果各个数据库的用户名和密码都一样的话,可以只写一个。

对于这些选项的解析的代码如下

$_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 表示是分布式, 0 表示的是集中式(也就是单一服务器)。

该选项的实现是在类 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’]表示的就是’DB_DEPLOY_TYPE’这个配置选项,上面的配置在使用之前都已经经过解析了,配置项都在$this->config数组中。至于是如何解析配置文件的,这里我们不做介绍,感兴趣的可以参考Think\Db类。

$this->multiConnect()函数就是用来进行分布式连接的,如果’DB_DEPLOY_TYPE’选项设置为1,该函数就会执行。否则直接执行$this->connect()函数。

‘DB_RW_SEPARATE’=>true

true 表示读写分离;false表示读写不分离。

这里需要注意的是,读写分离是以主从式数据库系统为前提的。该选项设置为true的时候主数据库写,从数据库读。

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’] 为true的时候采用读写分离,为false的时候读写不分离。读写分离为什么必须是主从式的呢?因为从服务器不能写只能读,如果向从服务器写入数据的话,数据是没法同步的。这样就会造成数据不一致的情况。所以说,如果我们的系统是主从式的话,我们必须采用读写分离。也就是说DB_RW_SEPARATE选项必须配置为true。

'DB_MASTER_NUM'=>1

该选项后面的数字表示读写分离后,主服务器的数量。因此该选项也是用于主从式数据库系统。

下面的代码是选择主服务器。

$m  =  floor(mt_rand(0,$this->config['master_num']-1));

主从式数据库读取的时候选择从服务器读的核心代码

$r = floor(mt_rand($this->config['master_num'],count($_config['hostname'])-1));   // 每次随机连接的数据库

其中$this->config[‘master_num’]表示主服务器的数量。

'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));   // 每次随机连接的数据库
}

以上是对每个选项的作用的实现代码进行了一个简单的说明。

下面我们来看其连接的部分

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);

看到这,我觉得大家应该对上面在介绍各个配置选项的代码的时候其中的$r和$m是什么作用了。

现在我们来看 $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,&#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());
    }
}

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

本文讲解了thinkphp 分布式数据库详解,更多相关内容请关注php中文网。

相关推荐:

如何通过ThinkPHP链接数据库

如何通过thinkphp连接多数据库

关于ThinkPHP 5.数据库的一些基本操作

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!

Déclaration:
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