Skip to content

Commit b6721c1

Browse files
author
Nicolas
committed
Document and test custom key distribution function
Solves issue phpredis#299
1 parent 804478e commit b6721c1

File tree

2 files changed

+47
-0
lines changed

2 files changed

+47
-0
lines changed

arrays.markdown

+5
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ By default and in order to be compatible with other libraries, phpredis will try
7171
For instance, the keys “{user:1}:name” and “{user:1}:email” will be stored on the same server as only “user:1” will be hashed. You can provide a custom function name in your redis array with the "function" option; this function will be called every time a key needs to be hashed. It should take a string and return a string.
7272

7373

74+
## Custom key distribution function
75+
In order to control the distribution of keys by hand, you can provide a custom function or closure that returns the server number, which is the index in the array of servers that you created the RedisArray object with.
76+
77+
For instance, instanciate a RedisArray object with `new RedisArray(array("us-host", "uk-host", "de-host"), array("distributor" => "dist"));` and write a function called "dist" that will return `2` for all the keys that should end up on the "de-host" server.
78+
7479
## Migrating keys
7580

7681
When a node is added or removed from a ring, RedisArray instances must be instanciated with a “previous” list of nodes. A single call to `$ra->_rehash()` causes all the keys to be redistributed according to the new list of nodes. Passing a callback function to `_rehash()` makes it possible to track the progress of that operation: the function is called with a node name and a number of keys that will be examined, e.g. `_rehash(function ($host, $count){ ... });`.

tests/array-tests.php

+42
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,47 @@ public function testDiscard() {
497497

498498
}
499499

500+
// Test custom distribution function
501+
class Redis_Distributor_Test extends TestSuite {
502+
503+
public $ra = NULL;
504+
505+
public function setUp() {
506+
507+
global $newRing, $oldRing, $useIndex;
508+
// create array
509+
$this->ra = new RedisArray($newRing, array('previous' => $oldRing, 'index' => $useIndex, 'distributor' => array($this, 'distribute')));
510+
}
511+
512+
public function testInit() {
513+
$this->ra->set('{uk}test', 'joe');
514+
$this->ra->set('{us}test', 'bob');
515+
}
516+
517+
public function distribute($key) {
518+
$matches = array();
519+
if (preg_match('/{([^}]+)}.*/', $key, $matches) == 1) {
520+
$countries = array('uk' => 0, 'us' => 1);
521+
if (array_key_exists($matches[1], $countries)) {
522+
return $countries[$matches[1]];
523+
}
524+
}
525+
return 2; // default server
526+
}
527+
528+
public function testDistribution() {
529+
$ukServer = $this->ra->_target('{uk}test');
530+
$usServer = $this->ra->_target('{us}test');
531+
$deServer = $this->ra->_target('{de}test');
532+
$defaultServer = $this->ra->_target('unknown');
533+
534+
$nodes = $this->ra->_hosts();
535+
$this->assertTrue($ukServer === $nodes[0]);
536+
$this->assertTrue($usServer === $nodes[1]);
537+
$this->assertTrue($deServer === $nodes[2]);
538+
$this->assertTrue($defaultServer === $nodes[2]);
539+
}
540+
}
500541

501542
function run_tests($className) {
502543
// reset rings
@@ -520,6 +561,7 @@ function run_tests($className) {
520561
run_tests('Redis_Rehashing_Test');
521562
run_tests('Redis_Auto_Rehashing_Test');
522563
run_tests('Redis_Multi_Exec_Test');
564+
run_tests('Redis_Distributor_Test');
523565
}
524566

525567
?>

0 commit comments

Comments
 (0)