当前位置 主页 > 网站技术 > 代码类 >

    Laravel数据库读写分离配置的方法

    栏目:代码类 时间:2019-11-06 15:02

    配置范例

    'mysql' => [
     'driver' => 'mysql', 
     'write' => [ 
     'host' => '192.168.1.180', 
     ], 
     'read' => [
     ['host' => '192.168.1.182'], 
     ['host' => '192.168.1.179'], 
     ],
     ... 
    ]

    'mysql' => [
     'driver' => 'mysql', 
     'write' => [ 
     'host' => '192.168.1.180', 
     ], 
     'read' => [
     'host' => [
     '192.168.1.182',
     '192.168.1.179'
     ], 
     ],
     ... 
    ]

    扩展配置范例

    'mysql' => [
     'driver' => 'mysql', 
     'write' => [ 
     'host' => '192.168.1.180', 
     'username' => 'write',
     'password' => 'write',
     ], 
     'read' => [
     [
     'host' => '192.168.1.182',
     'username' => 'read1',
     'password' => 'read1',
     ], 
     [
     'host' => '192.168.1.179',
     'username' => 'read2',
     'password' => 'read2',
     ], 
     ],
     ... 
    ]

    或者

    'mysql' => [
     'driver' => 'mysql', 
     'write' => [ 
     'host' => '192.168.1.180', 
     'username' => 'write',
     'password' => 'write',
     ], 
     'read' => [
     'host' => [
     '192.168.1.179',
     '192.168.1.182',
     ],
     'username' => 'read',
     'password' => 'read', 
     ],
     ... 
    ]

    公司数据库架构为一主多从,从库访问地址为唯一地址,该处方便负载均衡及扩展从库。所以最终线上采用的配置

    'mysql' => [
     'driver' => 'mysql', 
     'write' => [ 
     'host' => '192.168.1.180', 
     'username' => 'write',
     'password' => 'write',
     ], 
     'read' => [
     'host' => '192.168.1.179'
     'username' => 'read',
     'password' => 'read', 
     ],
     ... 
    ]

    代码分析

    授人以鱼不如授人以渔,之所以配置如此灵活的原因,以及如何查找到这些配置方式。主要通过查找代码,分析代码;相关代码都在下面粘出,这里就不做解释了,代码能说明一切;

    路径:vendor/laravel/framework/src/Illuminate/Database/Connectors/ConnectionFactory.php

    代码:

    class ConnectionFactory
    {
     ...
    
     /**
     * Get the read configuration for a read / write connection.
     *
     * @param array $config
     * @return array
     */
     protected function getReadConfig(array $config)
     {
     $readConfig = $this->getReadWriteConfig($config, 'read');
    
     if (isset($readConfig['host']) && is_array($readConfig['host'])) {
     $readConfig['host'] = count($readConfig['host']) > 1
     ? $readConfig['host'][array_rand($readConfig['host'])]
     : $readConfig['host'][0];
     }
    
     return $this->mergeReadWriteConfig($config, $readConfig);
     }
     
     ...
     
     /**
     * Get a read / write level configuration.
     *
     * @param array $config
     * @param string $type
     * @return array
     */
     protected function getReadWriteConfig(array $config, $type)
     {
     if (isset($config[$type][0])) {
     return $config[$type][array_rand($config[$type])];
     }
    
     return $config[$type];
     }
     
     ...
     
     /**
     * Merge a configuration for a read / write connection.
     *
     * @param array $config
     * @param array $merge
     * @return array
     */
     protected function mergeReadWriteConfig(array $config, array $merge)
     {
     return Arr::except(array_merge($config, $merge), ['read', 'write']);
     }
     
     ...
    }
     
     
    class Arr
    {
     ...
     
     /**
     * Get all of the given array except for a specified array of items.
     *
     * @param array $array
     * @param array|string $keys
     * @return array
     */
     public static function except($array, $keys)
     {
     static::forget($array, $keys);
     
     return $array;
     }
     
     ...
     
     /**
     * Remove one or many array items from a given array using "dot" notation.
     *
     * @param array $array
     * @param array|string $keys
     * @return void
     */
     public static function forget(&$array, $keys)
     {
     $original = &$array;
     
     $keys = (array) $keys;
     
     if (count($keys) === 0) {
     return;
     }
     
     foreach ($keys as $key) {
     $parts = explode('.', $key);
     
     while (count($parts) > 1) {
     $part = array_shift($parts);
     
     if (isset($array[$part]) && is_array($array[$part])) {
      $array = &$array[$part];
     } else {
      $parts = [];
     }
     }
     
     unset($array[array_shift($parts)]);
     
     // clean up after each pass
     $array = &$original;
     }
     }
     
     ...
    }