资讯专栏INFORMATION COLUMN

laravel5.2和redis_cluster配置

Joyven / 2994人阅读

摘要:纲要中集群的应用对集群模式的底层实现中集群的应用这部分我想分享下中集群的配置官网也有集群的配置讲解但是版还是有点不足只是说了将配置项设为,但光这样一个选项不能代表,一个新手直接可用集群这部分还包括客户端的事,所以后面我也会分享下关于的源码分

纲要:

laravel中redis集群的应用

predis对redis集群模式的底层实现

laravel中redis集群的应用

这部分我想分享下laravel5.2中redis集群的配置(官网也有redis集群的配置讲解,但是5.2版还是有点不足,只是说了将cluster配置项设为true,但光这样一个选项不能代表,一个新手直接可用redis集群,这部分还包括predis客户端的事,所以后面我也会分享下关于predis的源码分析)。

redis—cluster的搭建:Easy Building Redis-cluster (轻松搭建reids集群)

系统软件清单:

laravel版本:5.2

redis版本:>=3.0下载最新版即可

predis:>=1.0下载地址

配置文件:config/database.php

"redis" => [

    "cluster" => env("REDIS_CLUSTER", true),
    **"options"=>["cluster"=>"redis"]**,  //官网没说这个,这是必须的!!后面会讲为什么这么配?
    "default" => [
        "host" => env("REDIS_HOST", "127.0.0.1"), //任选一个master节点
        "port" => env("REDIS_PORT",6379),
        "database" => 0,
        "timeout"=>15,
        "read_write_timeout"=>1800 //redis客户端连接以后的读写超时时间(默认是60s)
    ],
    "extra"=>[                      
        "host"=>env("REDIS_EXTRA_HOST","127.0.0.1"),  //任意一个集群中的节点即可
        "port"=>env("REDIS_EXTRA_PORT",7001)
    ]
 ]

ok,配完上面的步骤,redis集群就可以用了.
具体使用redis集群的应用场景根据业务需求有很多种,比如集群存session等.
app("request")->session()->put("key","value");就存到集群中了.

predis对redis集群的底层实现

ok,想要了解配置文件中的参数,还是得看源代码,当然也是predis,上代码.

IlluminateSupportServiceProviderRedisServiceProvider;

    public function register()
    {
        $this->app->singleton("redis", function ($app) {
            return new Database($app["config"]["database.redis"]);
        });
    }
 

 IlluminateRedisDatabase;
    
     public function __construct(array $servers = [])
     {
        $cluster = Arr::pull($servers, "cluster");   //获取"cluster"的键值
       
        $options = (array) Arr::pull($servers, "options");
       //options 就是database.php中"options"的键值,是一个数组(但官网没有提到,是个坑.)
        if ($cluster) {  
            $this->clients = $this->createAggregateClient($servers, $options);   //集群模式"cluster=true"
        } else {
            $this->clients = $this->createSingleClients($servers, $options);   //单机模式 "cluster=false"
        }
    }

   protected function createAggregateClient(array $servers, array $options = [])
    {                
        return ["default" => new Client(array_values($servers), $options)];   //predis的Client类
    }
    


----------


注意:这里提醒一下各参数的值:
此时$servers=[
    [
      "host" => env("REDIS_HOST", "127.0.0.1"),
      "port" => env("REDIS_PORT",6379),
      "database" => 0,
      "timeout"=>15,
      "read_write_timeout"=>1800
    ],
    [
      "host"=>env("REDIS_EXTRA_HOST","127.0.0.1"),
      "port"=>env("REDIS_EXTRA_PORT",7001)
    ]
]
$options = ["cluster"=>"redis"]

其实到这儿,就可以解释在database.php中增加options选项,而且是必选项,因为底层代码需要判断数据切片的方式.
除了看源码,
predis的包文档也做了解释.https://packagist.org/packages/predis/predis
-------

接下来我们看看这些底层要初始化的类吧.

  PredisClient;
      public function __construct($parameters = null, $options = null)
    {
        $this->options = $this->createOptions($options ?: array());
        #$this->connection = $this->createConnection($parameters ?: array());
        #$this->profile = $this->options->profile;
    }
    
    protected function createOptions($options)
    {
        if (is_array($options)) {
            return new Options($options);  //如你所见,实例化Options类
        }

        if ($options instanceof OptionsInterface) {
            return $options;
        }

        throw new InvalidArgumentException("Invalid type for client options.");
    }
   
    public function __construct(array $options = array())
    {
        $this->input = $options;
        $this->options = array();
        $this->handlers = $this->getHandlers();
    }

$this->connection = $this->createConnection($parameters ?: array())

PredisClient 文件

    protected function createConnection($parameters)
    {
       # if ($parameters instanceof ConnectionInterface) {
       #     return $parameters;
       # }

       # if ($parameters instanceof ParametersInterface || is_string($parameters)) {
       #     return $this->options->connections->create($parameters);
       # }

       # if (is_array($parameters)) {
       #     if (!isset($parameters[0])) {
       #         return $this->options->connections->create($parameters);
       #     }

            $options = $this->options;

       #     if ($options->defined("aggregate")) {
       #         $initializer = $this->getConnectionInitializerWrapper($options->aggregate);
       #         $connection = $initializer($parameters, $options);
       #     } else {
       #         if ($options->defined("replication") && $replication = $options->replication) {
       #             $connection = $replication;
       #         } else {
                
                    $connection = $options->cluster; //
       #         }

                $options->connections->aggregate($connection, $parameters);
       #     }

            return $connection;
       # }

       # if (is_callable($parameters)) {
       #     $initializer = $this->getConnectionInitializerWrapper($parameters);
       #     $connection = $initializer($this->options);

       #     return $connection;
       # }

       # throw new InvalidArgumentException("Invalid type for connection parameters.");
    }
    
PredisConfigurationOptions;

    protected function getHandlers()
    {
        return array(
            "cluster" => "PredisConfigurationClusterOption",
            "connections" => "PredisConfigurationConnectionFactoryOption",
            #"exceptions" => "PredisConfigurationExceptionsOption",
            #"prefix" => "PredisConfigurationPrefixOption",
            #"profile" => "PredisConfigurationProfileOption",
            #"replication" => "PredisConfigurationReplicationOption",
        );
    }

    public function __get($option)
    {
        #if (isset($this->options[$option]) || array_key_exists($option, $this->options)) {
        #    return $this->options[$option];
        #}

         if (isset($this->input[$option]) || array_key_exists($option, $this->input)) {
            $value = $this->input[$option];
            unset($this->input[$option]);

        #    if (is_object($value) && method_exists($value, "__invoke"){
        #        $value = $value($this, $option);
        #    }

            if (isset($this->handlers[$option])) {
                $handler = $this->handlers[$option];
                $handler = new $handler(); //会实例化PredisConfigurationClusterOption类
                $value = $handler->filter($this, $value);
            }

            return $this->options[$option] = $value;
        }

       # if (isset($this->handlers[$option])) {
       #     return $this->options[$option] = $this->getDefault($option);
       # }

       # return;
    }
    
PredisConfigurationClusterOption文件

    public function filter(OptionsInterface $options, $value)
    {
        if (is_string($value)) {
            $value = $this->createByDescription($options, $value);
        }

       # if (!$value instanceof ClusterInterface) {
       #     throw new InvalidArgumentException(
       #         "An instance of type "PredisConnectionAggregateClusterInterface" was expected."
       #     );
       # }

        return $value;
    }
       
       
        protected function createByDescription(OptionsInterface $options, $id)
    {
        switch ($id) {
         * Abstraction for a cluster of aggregate connections to various Redis servers
 * implementing client-side sharding based on pluggable distribution strategies.
          # case "predis":
          # case "predis-cluster":
          #      return new PredisCluster(); 
          //这个模式是客户端通过CRC16算法在客户端进行数据切片,
          显然这种模式的集群是脆弱的,如果一个master节点挂了,
          那其备节点若也挂了,那么获取数据就成问题了;
          再有这种模式扩展性很差,维护成本高,
          因此这个模式不推荐.当然用最新predis不存在这个问题.
          我这边predis,1.0算比较老了.

            case "redis":
            case "redis-cluster":
                return new RedisCluster($options->connections);
            //这种模式是基于服务端的数据切片,相较于第一种模式,优点也显而易见,维护成本低,扩展性好等.
            default:
                return;
        }
    } 
    
        public function __get($option)
    {
        #if (isset($this->options[$option]) || array_key_exists($option, $this->options)) {
        #    return $this->options[$option];
        #}

        # if (isset($this->input[$option]) || array_key_exists($option, $this->input)) {
        #    $value = $this->input[$option];
        #    unset($this->input[$option]);

        #    if (is_object($value) && method_exists($value, "__invoke"){
        #        $value = $value($this, $option);
        #    }

        #    if (isset($this->handlers[$option])) {
        #       $handler = $this->handlers[$option];
        #        $handler = new $handler(); 
        #        $value = $handler->filter($this, $value);
        #    }

        #    return $this->options[$option] = $value;
        #}

         if (isset($this->handlers[$option])) {  //$options="connections"       
            return $this->options[$option] = $this->getDefault($option);
       # }

       # return;
    }  
    
    public function getDefault($option)
    {
        if (isset($this->handlers[$option])) {
            $handler = $this->handlers[$option]; //$handler = "PredisConfigurationConnectionFactoryOption";
            $handler = new $handler();

            return $handler->getDefault($this);
        }
    }
    
 PredisConfigurationConnectionFactoryOption文件
    public function getDefault(OptionsInterface $options)
    {
        return new Factory(); //最后实例化了一个"工厂"类
    }

$this->profile = $this->options->profile;

PredisConfigurationProfileOption文件


        public function __get($option)
    {
        #if (isset($this->options[$option]) || array_key_exists($option, $this->options)) {
        #    return $this->options[$option];
        #}

        # if (isset($this->input[$option]) || array_key_exists($option, $this->input)) {
        #    $value = $this->input[$option];
        #    unset($this->input[$option]);

        #    if (is_object($value) && method_exists($value, "__invoke"){
        #        $value = $value($this, $option);
        #    }

        #    if (isset($this->handlers[$option])) {
        #       $handler = $this->handlers[$option];
        #        $handler = new $handler(); 
        #        $value = $handler->filter($this, $value);
        #    }

        #    return $this->options[$option] = $value;
        #}

         if (isset($this->handlers[$option])) {  //$options="profile"       
            return $this->options[$option] = $this->getDefault($option);
       # }

       # return;
    }  
    
        public function getDefault($option)
    {
        if (isset($this->handlers[$option])) {
            $handler = $this->handlers[$option]; //$handler = "PredisConfigurationProfileOption";
            $handler = new $handler();

            return $handler->getDefault($this);
        }
    }
    
 PredisConfigurationProfileOption文件
     public function getDefault(OptionsInterface $options)
    {
        $profile = Factory::getDefault(); //实例化了PredisProfileRedisVersion300类
        $this->setProcessors($options, $profile);

        return $profile;  
    }
    
    

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/61869.html

相关文章

  • laravel5.2redis_cluster配置

    摘要:纲要中集群的应用对集群模式的底层实现中集群的应用这部分我想分享下中集群的配置官网也有集群的配置讲解但是版还是有点不足只是说了将配置项设为,但光这样一个选项不能代表,一个新手直接可用集群这部分还包括客户端的事,所以后面我也会分享下关于的源码分 纲要: laravel中redis集群的应用 predis对redis集群模式的底层实现 laravel中redis集群的应用 这部分我想分享...

    JerryC 评论0 收藏0
  • ubuntu/centos 搭建 搭建 redis 集群

    摘要:环境配置机器下载独立文件位置安装关键点工具实现集群复制到目录下。创建集群命令发现环境需要下安装方案下安装方案如果不好用,可以切换到淘宝源然后再次执行即可。说明集群正常工作。互联网时代,时刻要保持学习,携手千锋。 1 环境配置: ubuntu16.04 redis3.0.62 机器: 192.168.50.156 192.168.50.154 192.168.50.1553 下载red...

    jcc 评论0 收藏0

发表评论

0条评论

Joyven

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<