Heim >Backend-Entwicklung >PHP-Tutorial >Detaillierte Erläuterung der verteilten Datenbankverbindungsmethode des ThinkPHP-Frameworks

Detaillierte Erläuterung der verteilten Datenbankverbindungsmethode des ThinkPHP-Frameworks

不言
不言Original
2018-05-03 17:41:432341Durchsuche

Dieser Artikel stellt hauptsächlich die verteilte Datenbankverbindungsmethode des ThinkPHP-Frameworks vor und analysiert die verteilte Datenbankverbindungsmethode, die Betriebsfähigkeiten und die damit verbundenen Vorsichtsmaßnahmen im Detail in Form von Beispielen. Freunde in Not können sich darauf beziehen

In diesem Artikel wird die verteilte Datenbankverbindungsmethode des ThinkPHP-Frameworks anhand von Beispielen analysiert. Teilen Sie es als Referenz mit allen. Die Details lauten wie folgt:

Thinkphp ist ein beliebtes Framework in China, und ich glaube, dass es viele Leute geben muss, die es verwenden. In diesem Artikel analysieren wir einen wichtigen Teil von Thinkphp – die Verbindung verteilter Datenbanken.

Natürlich sind wir nicht hier, um zu erklären, wie das Modell zum Hinzufügen, Löschen, Ändern und Abfragen der Datenbank verwendet wird. Wir führen eine Analyse des zugrunde liegenden Verbindungscodes durch, die Ihnen helfen kann, den Betrieb der Datenbank durch thinkphp besser zu verstehen. Um unsere zukünftige Nutzung zu erleichtern.

1. Einzelne Datenbankverbindung

Bei Verwendung ist die Verbindungskonfiguration einer einzelnen Datenbank sehr einfach. Wir müssen nur einige Informationen in der Konfigurationsdatei konfigurieren.

'DB_TYPE' => 'mysql',
'DB_HOST' => '192.168.5.102',
'DB_NAME' => 'databasename',
'DB_USER' => 'user',
'DB_PWD' => 'password',
'DB_PORT' => '3306',
'DB_PREFIX' => 'onmpw_',

Sie können es verwenden, nachdem die Einrichtung abgeschlossen ist. Der Standardwert ist eine einzelne Datenbankverbindung.

2. Verteilte Datenbankverbindung

Die Verbindung einer einzelnen Datenbank ist sehr einfach. Konzentrieren wir uns auf die Analyse der Verbindung einer verteilten Datenbank.

'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' => '', // 指定从服务器序号

Folgen Sie der obigen Konfiguration, um eine Verbindung zur verteilten Datenbank herzustellen.

Sehen wir uns die folgenden Optionen an

'DB_HOST'

Eine verteilte Datenbank erfordert mehrere Server Geben Sie Adressen ein und trennen Sie die einzelnen Adressen durch Kommas. Wenn es sich um eine Master-Slave-Verteilung handelt, muss die vorherige Adresse die Adresse der Master-Datenbank sein.

Für die folgenden Benutzernamen, Passwörter, Abhörports usw. notieren Sie sich natürlich so viele, wie Sie haben. Wenn der Benutzername und das Passwort jeder Datenbank gleich sind, können Sie nur eine schreiben.

Der Code zum Parsen dieser Optionen lautet wie folgt

$_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 bedeutet Verteilung In der Formel steht 0 für zentralisiert (d. h. einen einzelnen Server).

Die Implementierung dieser Option befindet sich in der Klasse

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'] und stellt die 是'DB_DEPLOY_TYPE'-Konfigurationsoption dar. Die obige Konfiguration wurde vor der Verwendung analysiert und alle Konfigurationselemente sind vorhanden im $this->config-Array. Was das Parsen der Konfigurationsdatei betrifft, werden wir hier nicht vorstellen. Interessierte können sich auf die ThinkDb-Klasse beziehen. Die Funktion

$this->multiConnect() wird für verteilte Verbindungen verwendet. Wenn die Option 'DB_DEPLOY_TYPE' auf 1 gesetzt ist, wird diese Funktion ausgeführt. Andernfalls führen Sie die Funktion $this->connect() direkt aus.

'DB_RW_SEPARATE'=>true

true bedeutet, dass Lesen und Schreiben getrennt sind; falsch bedeutet, dass Lesen und Schreiben nicht getrennt sind.

Hier ist zu beachten, dass die Trennung von Lesen und Schreiben auf dem Master-Slave-Datenbanksystem basiert. Wenn diese Option auf „true“ gesetzt ist, schreibt die Master-Datenbank und die Slave-Datenbank liest. Wenn

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'] wahr ist, werden Lesen und Schreiben getrennt, und wenn es falsch ist, werden Lesen und Schreiben nicht getrennt. Warum muss die Trennung von Lesen und Schreiben Master-Slave sein? Da der Slave-Server nicht schreiben und nur lesen kann, können die Daten nicht synchronisiert werden, wenn Daten auf den Slave-Server geschrieben werden. Dies führt zu Dateninkonsistenzen. Wenn unser System ein Master-Slave-System ist, müssen wir daher eine Lese-/Schreibtrennung verwenden. Mit anderen Worten: Die Option DB_RW_SEPARATE muss als „true“ konfiguriert werden.

'DB_MASTER_NUM'=>1

Die Zahl nach dieser Option gibt die Anzahl der Master-Server nach der Lese- und Schreibtrennung an. Daher wird diese Option auch in Master-Slave-Datenbanksystemen verwendet.

Der folgende Code wählt den Hauptserver aus.

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

Wählen Sie beim Lesen aus der Master-Slave-Datenbank den Kerncode aus, der vom Server gelesen werden soll

Kopieren Sie den Code Der Code lautet wie folgt:

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

wobei $this->config['master_num'] die Anzahl der Master-Server angibt.

'DB_SLAVE_NO'=> ''

Geben Sie die Seriennummer des Slave-Servers zum Lesen von Daten an. Wenn nicht festgelegt, wird die Anzahl der Slave-Server anhand der Anzahl der Master-Server berechnet und dann einer zufällig zum Lesen ausgewählt.

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

Das Obige ist eine einfache Erklärung des Implementierungscodes der Funktion jeder Option.

Werfen wir einen Blick auf den Verbindungsteil

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

Da ich das sehe, denke ich, dass jeder die Funktionen von $r und $m verstehen sollte, wenn er den Code für jede der oben genannten Konfigurationsoptionen vorstellt.

现在我们来看 $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的功能已经相当完善,足够我们使用了。但是还是希望thinkphp以后越来越完善。

相关推荐:

thinkPHP5.0框架命名空间详解




Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der verteilten Datenbankverbindungsmethode des ThinkPHP-Frameworks. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn