Heim  >  Artikel  >  Backend-Entwicklung  >  So stellen Sie eine Verbindung zu einer verteilten Datenbank in Thinkphp her

So stellen Sie eine Verbindung zu einer verteilten Datenbank in Thinkphp her

*文
*文Original
2017-12-23 14:00:312711Durchsuche

Thinkphp ist ein Mainstream-Framework in China und ich glaube, dass es viele Leute geben muss, die es nutzen. Heute werfen wir einen Blick darauf, wie man in Thinkphp eine Verbindung zu einer verteilten Datenbank herstellt.

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, die Funktionsweise 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 Einstellung abgeschlossen ist. Der Standardwert ist eine einzelne Datenbankverbindung.

2. Verteilte Datenbankverbindung

Die Verbindung zu einer einzelnen Datenbank ist sehr einfach.

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

Befolgen Sie die obige Konfiguration, um eine Verbindung zur verteilten Datenbank herzustellen.

Sehen wir uns die folgenden Optionen an

'DB_HOST'

Wenn bei verteilten Datenbanken mehrere Server vorhanden sind, müssen Sie mehrere Serveradressen eingeben und diese durch getrennt verwenden 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 verteilt, 0 bedeutet zentralisiert (d. h. ein einzelner Server).

Die Implementierung dieser Option befindet sich in der Klasse 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'] stellt die Konfigurationsoption 'DB_DEPLOY_TYPE' dar. Die obige Konfiguration wird verwendet wurden bereits zuvor analysiert und die Konfigurationselemente befinden sich alle im Array $this->config. Was das Parsen der Konfigurationsdatei betrifft, werden wir hier nicht vorstellen. Interessierte können sich auf die ThinkDb-Klasse beziehen.

$this->multiConnect()-Funktion 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

wahr 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.

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’] verwendet die Lese- und Schreibtrennung, wenn es wahr ist, und trennt Lesen und Schreiben nicht, wenn es falsch ist. 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 beim Schreiben auf den Slave-Server nicht synchronisiert 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 Primärserver 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 Slave-Server gelesen werden soll

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

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

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

Angesichts dessen denke ich, dass sich jeder über $r und $m im Klaren sein sollte, wenn er den Code für jede der oben genannten Konfigurationsoptionen einführt geht das?

Sehen wir uns nun $r == $m ? false an: Wenn das Lesen und Schreiben der Datenbank nicht getrennt ist und das Lesen und Schreiben ein Server ist, ist der an die Verbindungsfunktion übergebene Wert falsch . Oder wenn der Master-Slave-Schreibvorgang getrennt ist, ist der an connect übergebene Wert ebenfalls falsch. Aus dem obigen Code sehen wir, dass $db_master gesetzt wird, wenn $r und $m nicht gleich sind. Tatsächlich entspricht es einem Backup. Wenn der ausgewählte $r-Server ausfällt und keine Verbindung hergestellt werden kann, wird eine Verbindung zu $db_master hergestellt.

Der dritte Parameter der connect()-Funktion gibt tatsächlich an, ob eine Backup-Verbindung ausgewählt werden soll, wenn die $db_config-Serververbindung fehlschlägt. False bedeutet keine erneute Verbindung, andere Werte bedeuten eine erneute Verbindung.

Der Kerncode lautet wie folgt

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

Auf diese Weise sind $r und $m für den Master-Slave-Typ definitiv nicht gleich. Wenn daher der ausgewählte Slave-Server beim Lesen von Daten ausfällt, fungiert der Master-Server als Backup und geht schließlich zum Lesen zum Master-Server. Es kann die Aktualität des Datenlesens sicherstellen.

Allerdings habe ich immer noch das Gefühl, dass es noch nicht perfekt ist. Wenn mehrere Slave-Server vorhanden sind und sowohl der Slave-Server als auch der beim Lesen ausgewählte Master-Server fehlschlagen, schlägt das Lesen der Daten fehl. Zu diesem Zeitpunkt sollte es sicherer sein, wenn andere Slave-Server erneut gelesen werden können. Natürlich sind die aktuellen Funktionen von thinkphp durchaus vollständig und für unsere Nutzung ausreichend. Aber ich hoffe immer noch, dass thinkphp in Zukunft immer perfekter wird.

Ich hoffe, dass die obige Einführung für alle hilfreich sein kann, die thinkphp für die Entwicklung verwenden.

Verwandte Empfehlungen:

ThinkPHP5-Framework-Grundkenntnisse, Entwicklungsspezifikationen und Verzeichnisstruktur

ThinkPHP Datei-Caching-Code-Sharing

ThinkPHP Datenbank- und Modellleistungsbewertung


Das obige ist der detaillierte Inhalt vonSo stellen Sie eine Verbindung zu einer verteilten Datenbank in Thinkphp her. 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