thinkphp 분산 데이터베이스에 대한 자세한 설명

jacklove
풀어 주다: 2023-04-01 09:42:02
원래의
2347명이 탐색했습니다.

1. 분산 데이터베이스란:

tp의 ​​분산 데이터베이스는 주로 다음 구성을 통해 구성됩니다.

'DB_DEPLOY_TYPE' => 1,// 데이터베이스 배포 방법: 0 중앙 집중식(단일 서버) , 1개 분산(마스터-슬레이브 서버)

2. 마스터-슬레이브 서버의 읽기-쓰기 분리는 무엇입니까?

master 데이터베이스 n개의 해당 슬레이브 데이터베이스가 있으며, 슬레이브 데이터베이스는 해당 슬레이브 데이터베이스를 하나만 가질 수 있습니다. 마스터-슬레이브 데이터베이스의 쓰기 작업에는 마스터 데이터베이스를 사용해야 하고, 읽기 작업에는 슬레이브 데이터베이스를 사용합니다. 마스터 데이터베이스와 슬레이브 데이터베이스는 항상 데이터 일관성을 유지합니다. 데이터베이스 일관성을 유지하는 원칙은 메인 데이터베이스의 데이터가 변경되면 작업이 메인 데이터베이스 로그에 기록되고 슬레이브 데이터베이스는 계속해서 메인 데이터베이스의 로그를 읽고 자체 로그에 저장하는 것입니다. 시스템을 실행한 다음 이를 실행하여 마스터-슬레이브 데이터베이스의 일관성을 유지합니다.

3. 자세한 설명

1. 단일 데이터베이스 연결

사용 시 단일 데이터베이스의 연결 구성은 매우 간단합니다. 구성 파일에서 일부 정보만 구성하면 됩니다.

'DB_TYPE' => 'mysql',
'DB_HOST' => '192.168.5.102',
'DB_NAME' => 'databasename',
'DB_USER' => 'user',
'DB_PWD' => 'password',
'DB_PORT' => '3306',
'DB_PREFIX' => 'onmpw_',
로그인 후 복사

설정이 완료된 후 사용하시면 됩니다. 기본값은 단일 데이터베이스 연결입니다.

2. 분산 데이터베이스 연결

단일 데이터베이스 연결은 매우 간단합니다. 분산 데이터베이스의 연결을 집중적으로 살펴보겠습니다.

'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'           =>  '', // 指定从服务器序号
로그인 후 복사

위 구성에 따라 분산 데이터베이스에 연결합니다.

다음 옵션을 살펴보겠습니다

'DB_HOST'

분산 데이터베이스의 경우 서버가 여러 개인 경우 여러 서버 주소를 입력하고 각 주소를 쉼표로 구분해야 합니다. 마스터-슬레이브 배포인 경우 이전 주소는 기본 데이터베이스의 주소여야 합니다.

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

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

$_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.数据库的一些基本操作

위 내용은 thinkphp 분산 데이터베이스에 대한 자세한 설명의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

관련 라벨:
원천:php.cn
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿
회사 소개 부인 성명 Sitemap
PHP 중국어 웹사이트:공공복지 온라인 PHP 교육,PHP 학습자의 빠른 성장을 도와주세요!