mirror of
https://github.com/predis/predis.git
synced 2026-08-22 13:41:57 +00:00
09de7be7cb
This is mainly in response to the longstanding issue #36 in which my proposed solution was fine in terms of functionalities, but eventually never made into the repository since it was far from being clean enough for my taste. Now developers can optionally pass a callable object when creating the hashring instance to decide how the distributor should extract the hash from a node (really a connection instance) to populate the ring: use Predis\Cluster\Distribution\HashRing; use Predis\Connection\PredisCluster; $servers = array( 'tcp://10.0.0.1?alias=node01', 'tcp://10.0.0.2?alias=node02', ); $options = array( 'nodehash' => function ($connection) { return $connection->getParameters()->alias; }, 'cluster' => function ($options) { $replicas = HashRing::DEFAULT_REPLICAS; $hashring = new HashRing($replicas, $options->nodehash); $cluster = new PredisCluster($hashring); return $cluster; }, ); $client = new Predis\Client($servers, $options); Both HashRing and KetamaPureRing in the Predis\Cluster\Distribution namespace support this new approach.
154 lines
3.7 KiB
PHP
154 lines
3.7 KiB
PHP
<?php
|
|
|
|
/*
|
|
* This file is part of the Predis package.
|
|
*
|
|
* (c) Daniele Alessandri <suppakilla@gmail.com>
|
|
*
|
|
* For the full copyright and license information, please view the LICENSE
|
|
* file that was distributed with this source code.
|
|
*/
|
|
|
|
namespace Predis\Cluster\Distribution;
|
|
|
|
/**
|
|
* @todo To be improved.
|
|
*/
|
|
class HashRingTest extends DistributionStrategyTestCase
|
|
{
|
|
/**
|
|
* {@inheritdoc}
|
|
*/
|
|
public function getDistributorInstance()
|
|
{
|
|
return new HashRing();
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testHash()
|
|
{
|
|
$ring = $this->getDistributorInstance();
|
|
|
|
$this->assertEquals(crc32('foobar'), $ring->hash('foobar'));
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testSingleNodeInRing()
|
|
{
|
|
$node = '127.0.0.1:7000';
|
|
|
|
$ring = $this->getDistributorInstance();
|
|
$ring->add($node);
|
|
|
|
$expected = array_fill(0, 20, $node);
|
|
$actual = $this->getNodes($ring, 20);
|
|
|
|
$this->assertSame($expected, $actual);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testMultipleNodesInRing()
|
|
{
|
|
$nodes = array(
|
|
'127.0.0.1:7000',
|
|
'127.0.0.1:7001',
|
|
'127.0.0.1:7002',
|
|
);
|
|
|
|
$ring = $this->getDistributorInstance();
|
|
foreach ($nodes as $node) {
|
|
$ring->add($node);
|
|
}
|
|
|
|
$expected = array(
|
|
'127.0.0.1:7001',
|
|
'127.0.0.1:7001',
|
|
'127.0.0.1:7001',
|
|
'127.0.0.1:7002',
|
|
'127.0.0.1:7002',
|
|
'127.0.0.1:7001',
|
|
'127.0.0.1:7001',
|
|
'127.0.0.1:7000',
|
|
'127.0.0.1:7001',
|
|
'127.0.0.1:7002',
|
|
'127.0.0.1:7002',
|
|
'127.0.0.1:7002',
|
|
'127.0.0.1:7002',
|
|
'127.0.0.1:7000',
|
|
'127.0.0.1:7002',
|
|
'127.0.0.1:7002',
|
|
'127.0.0.1:7002',
|
|
'127.0.0.1:7000',
|
|
'127.0.0.1:7001',
|
|
'127.0.0.1:7002',
|
|
);
|
|
|
|
$actual = $this->getNodes($ring, 20);
|
|
|
|
$this->assertSame($expected, $actual);
|
|
}
|
|
|
|
/**
|
|
* @group disconnected
|
|
*/
|
|
public function testSubsequendAddAndRemoveFromRing()
|
|
{
|
|
$ring = $this->getDistributorInstance();
|
|
|
|
$expected1 = array_fill(0, 10, '127.0.0.1:7000');
|
|
$expected3 = array_fill(0, 10, '127.0.0.1:7001');
|
|
$expected2 = array(
|
|
'127.0.0.1:7001',
|
|
'127.0.0.1:7001',
|
|
'127.0.0.1:7001',
|
|
'127.0.0.1:7001',
|
|
'127.0.0.1:7001',
|
|
'127.0.0.1:7001',
|
|
'127.0.0.1:7001',
|
|
'127.0.0.1:7000',
|
|
'127.0.0.1:7001',
|
|
'127.0.0.1:7000',
|
|
);
|
|
|
|
$ring->add('127.0.0.1:7000');
|
|
$actual1 = $this->getNodes($ring, 10);
|
|
|
|
$ring->add('127.0.0.1:7001');
|
|
$actual2 = $this->getNodes($ring, 10);
|
|
|
|
$ring->remove('127.0.0.1:7000');
|
|
$actual3 = $this->getNodes($ring, 10);
|
|
|
|
$this->assertSame($expected1, $actual1);
|
|
$this->assertSame($expected2, $actual2);
|
|
$this->assertSame($expected3, $actual3);
|
|
}
|
|
|
|
/**
|
|
* @todo This tests should be moved in Predis\Cluster\Distribution\DistributionStrategyTestCase
|
|
* @group disconnected
|
|
*/
|
|
public function testCallbackToGetNodeHash()
|
|
{
|
|
$node = '127.0.0.1:7000';
|
|
$replicas = HashRing::DEFAULT_REPLICAS;
|
|
$callable = $this->getMock('stdClass', array('__invoke'));
|
|
|
|
$callable->expects($this->once())
|
|
->method('__invoke')
|
|
->with($node)
|
|
->will($this->returnValue($node));
|
|
|
|
$ring = new HashRing($replicas, $callable);
|
|
$ring->add($node);
|
|
|
|
$this->getNodes($ring);
|
|
}
|
|
}
|