2013-03-01 81 views
1

我试图使用Predis sharding别名,因为described here。我的代码基本相同,但我只返回空数组。我的哈希键需要在他们周围吗? (编辑:不,就试了一下)Predis Alias Sharding

$api->get("/test", function() { 

    $servers = [ 
     ["alias" => "metadata", "port" => 6380], 
     ["alias" => "relations", "port" => 6381], 
     ["alias" => "dim_provider", "port" => 6382], 
     ["alias" => "dim_revctrcode", "port" => 6383], 
     ["alias" => "dim_enccode", "port" => 6384], 
     ["alias" => "dim_pos", "port" => 6385] 
    ]; 

    $options = [ 

     "nodehash" => function ($connection) { return $connection->getParameters()->alias; }, 

     "cluster" => function ($options) { 
     $replicas = Predis\Cluster\Distribution\HashRing::DEFAULT_REPLICAS; 
     $hashring = new Predis\Cluster\Distribution\HashRing($replicas, $options->nodehash); 
     $cluster = new Predis\Connection\PredisCluster($hashring); 

     return $cluster; 
     } 
    ]; 

    $redis = new Predis\Client($servers, $options); 

    try { 
     $test = $redis->scard("dim_provider"); 
     print_r($test); // Prints 0 for scard or empty Array for hgetall 
    } catch (Exception $e) { 
     print $e->getMessage(); 
    } 

    $redis = new Predis\Client(["port" => 6382]); 
    $test = $redis->scard("dim_provider"); 
    print_r($test); // Works. 
    }); 

编辑:它也可以,如果我只放了一台服务器$servers阵列英寸所以看起来哈希算法并不正确。当我在nodehash的返回值前面抛出一些回声时,我可以看到它正在返回别名。

回答

1

分配一个dim_provider别名到Redis的连接,并试图从服务器获取一个关键命名dim_provider是两回事。

在您的脚本中,您尝试使用连接别名(而不是通常的ip:port对)设置Redis实例的群集来计算您的密钥空间在作为data shards的多个Redis服务器之间的分布情况。使用此设置,密钥dim_provider根据基础分发算法进行分片,并可存储在组成群集的6台服务器中的任何一台服务器上,并在$servers阵列中定义。

+0

谢谢。很明显,我误解别名分片。我的目标是将每个维度托管在一个单独的分片上。假设我有一个名为'dim_provider'的集合,并使用了名为'dim_provider:id'的散列,API将连接到redis集群并根据所需的密钥知道要去哪个服务器。我是否需要编写自己的分销策略?在我的PHP脚本中映射key:port对可能会更容易。 – 2013-03-02 15:07:16

+0

通常,在使用客户端分片时,您不关心要存储哪些服务器密钥,理想情况下,密钥空间均匀分布在您的Redis实例中。通过分配'weight'参数或使用密钥标签来确保某些密钥组存储在同一个分片上,通过计算散列值只能在包含在{}中的密钥部分中,确实可以平衡每台服务器上的负载,但是您将无法基于密钥强制执行目标服务器。 – nrk 2013-03-02 16:31:10

+0

从某种意义上说,您的用例可以被看作是一种非常专业化的分区,但与用于通过客户端分片分发密钥的常用策略无法很好地发挥作用。考虑你试图达到的目标,我只是使用'Predis \ Client'的多个实例,每个服务器都有一个实例,但是没有什么能阻止你通过实现分析每个Redis的'Predis \ Connection \ ClusterConnectionInterface'编写你自己的集群后端类命令来决定使用哪个服务器。定制化毕竟是Predis的卖点之一。 – nrk 2013-03-02 16:32:06

0

我想增加一次nrk让我走上正确的轨道时,实现我的集群策略是多么容易。这是一个写得很好的图书馆。

$api->get("/test", function() { 

    Class KeyCluster extends Predis\Connection\PredisCluster { 

     public function __construct() { 
     $this->pool = Array(); 
     } 

     public function add (Predis\Connection\SingleConnectionInterface $connection) { 
     $parameters = $connection->getParameters(); 
     if (isset($parameters->table)) { 
      $this->pool[$parameters->table] = $connection; 
     } else { 
      $this->pool[] = $connection; 
     } 
     } 

     public function getConnection (Command\CommandInterface $command) { 
     $key = $command->getArgument(0); 
     $table = explode(":", $key)[0]; 
     return isset($this->pool[$table]) ? $this->pool[$table] : null; 
     } 
    } 

    $redis = new Predis\Client([ 
     "tcp://127.0.0.1:6382?table=dim_provider", 
     "tcp://127.0.0.1:6383?table=dim_pos" 
    ],[ 
     "cluster" => new KeyCluster 
    ]); 

    $result = $redis->scard("dim_provider"); 
    print_r($result); 
    }); 
+0

您的方法基本上与我的想法相同,但我的建议是,您应该通过实施'Predis \ Connection \ ClusterConnectionInterface'而不是扩展'Predis \ Connection \ PredisCluster'来真正创建集群类。仅从您的类中'Predis \ Connection \ PredisCluster'复制代码的相关部分就没有问题,只是父类中有很多东西不需要,或者甚至在您的情况下都没有意义。事实上,你最终会写更多的代码,但这只是你写一次才能获得更清晰的解决方案。 – nrk 2013-03-06 22:21:23

+0

这实际上是我最终做的。在那里没有太多额外的东西,但它确实消除了依赖性并允许进一步的自定义行为。 – 2013-03-21 03:27:20