Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Document and test custom key distribution function

Solves issue #299
  • Loading branch information...
commit b6721c1292c0203741bee6fef0ab07e6225283c0 1 parent 804478e
Nicolas authored
Showing with 47 additions and 0 deletions.
  1. +5 −0 arrays.markdown
  2. +42 −0 tests/array-tests.php
View
5 arrays.markdown
@@ -71,6 +71,11 @@ By default and in order to be compatible with other libraries, phpredis will try
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.
+## Custom key distribution function
+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.
+
+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.
+
## Migrating keys
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){ ... });`.
View
42 tests/array-tests.php
@@ -497,6 +497,47 @@ public function testDiscard() {
}
+// Test custom distribution function
+class Redis_Distributor_Test extends TestSuite {
+
+ public $ra = NULL;
+
+ public function setUp() {
+
+ global $newRing, $oldRing, $useIndex;
+ // create array
+ $this->ra = new RedisArray($newRing, array('previous' => $oldRing, 'index' => $useIndex, 'distributor' => array($this, 'distribute')));
+ }
+
+ public function testInit() {
+ $this->ra->set('{uk}test', 'joe');
+ $this->ra->set('{us}test', 'bob');
+ }
+
+ public function distribute($key) {
+ $matches = array();
+ if (preg_match('/{([^}]+)}.*/', $key, $matches) == 1) {
+ $countries = array('uk' => 0, 'us' => 1);
+ if (array_key_exists($matches[1], $countries)) {
+ return $countries[$matches[1]];
+ }
+ }
+ return 2; // default server
+ }
+
+ public function testDistribution() {
+ $ukServer = $this->ra->_target('{uk}test');
+ $usServer = $this->ra->_target('{us}test');
+ $deServer = $this->ra->_target('{de}test');
+ $defaultServer = $this->ra->_target('unknown');
+
+ $nodes = $this->ra->_hosts();
+ $this->assertTrue($ukServer === $nodes[0]);
+ $this->assertTrue($usServer === $nodes[1]);
+ $this->assertTrue($deServer === $nodes[2]);
+ $this->assertTrue($defaultServer === $nodes[2]);
+ }
+}
function run_tests($className) {
// reset rings
@@ -520,6 +561,7 @@ function run_tests($className) {
run_tests('Redis_Rehashing_Test');
run_tests('Redis_Auto_Rehashing_Test');
run_tests('Redis_Multi_Exec_Test');
+ run_tests('Redis_Distributor_Test');
}
?>
Please sign in to comment.
Something went wrong with that request. Please try again.