2013-03-01 1 views
1

Я пытаюсь использовать Predis sharding по псевдониму, как described here. Мой код в основном идентичен, но я возвращаю только пустые массивы. Могут ли мои хэш-ключи {} вокруг них? (EDIT: Нет, просто попытался его)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. 
    }); 

EDIT: Это также работает, если я только положить один сервер в $servers массиве. Поэтому кажется, что хеширование работает неправильно. Когда я бросаю некоторые эхо-сигналы перед возвращаемым значением в nodehash, я вижу, что он возвращает псевдоним.

ответ

1

Назначение dim_providerпсевдоним к соединению Redis и пытается получить ключ имени dim_provider от сервера это две разные вещи.

В вашем скрипте вы пытаетесь настроить кластер экземпляров Redis с использованием псевдонимов соединений (вместо обычных пар ip:port), чтобы рассчитать распределение вашего пространства ключей между несколькими серверами Redis, действующими как ваш data shards. Используя эту настройку, ключ dim_provider оканчивается соответствующим алгоритму распределения и может быть сохранен на любом из 6 серверов, составляющих ваш кластер, и определен в массиве $servers.

+0

Спасибо. Ясно, что я неправильно понимаю псевдоним. Моя цель - разместить каждое измерение на отдельном осколке. Скажем, у меня есть набор под названием 'dim_provider' в сочетании с хэшами, называемый' dim_provider: id'. API будет подключаться к кластеру redis и знать, к какому серверу нужно перейти на основе необходимого ему ключа. Должен ли я написать свою собственную стратегию распространения? Вероятно, было бы проще сопоставить пары key: port внутри моего PHP-скрипта. –

+0

Обычно при использовании наложения на стороне клиента вам все равно, какие ключи сервера хранятся, в идеале, пространство ключей равномерно распределяется между вашими экземплярами Redis. Вы действительно можете сбалансировать нагрузку на каждом сервере, назначив параметр «weight» или используя ключевые теги, чтобы гарантировать, что определенные группы ключей хранятся на одном и том же осколке, вычисляя хэш только на части ключа, завернутого в '{}' , но вы не сможете принудительно использовать целевой сервер на основе ключа. – nrk

+0

В некотором смысле ваш прецедент можно рассматривать как очень специализированный вид секционирования, но он не очень хорошо работает с общими стратегиями, используемыми для распространения ключей с наложением на стороне клиента. Учитывая то, что вы пытаетесь достичь, я просто использовал несколько экземпляров «Predis \ Client», по одному для каждого сервера, но ничто не мешает вам писать собственный кластерный кластерный класс, реализуя «Predis \ Connection \ ClusterConnectionInterface», который анализирует каждый Redis команду для его ключей, чтобы решить, какой сервер следует использовать. В конце концов, настройка является одной из точек продажи Predis. – nrk

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

+0

Это на самом деле то, что я закончил делать. В нем не было слишком много лишнего, но оно устраняет зависимость и допускает дальнейшее индивидуальное поведение. –

 Смежные вопросы

  • Нет связанных вопросов^_^