2013-03-01 79 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