如题分享一老外实现思路,抛开redis自身配置主从外模拟memcache中hash多服务器承载
原文https://github.com/jdp/redisent/blob/master/redisent_cluster.php
作者思路不错,大家可以借鉴
-
php
-
/**
-
* Redisent, a Redis interface for the modest
-
* @author Justin Poliey
-
* @copyright 2009 Justin Poliey
-
* @license http://www.opensource.org/licenses/mit-license.php The MIT License
-
* @package Redisent
-
*/
-
-
require \'redisent.php\';
-
-
/**
-
* A generalized Redisent interface for a cluster of Redis servers
-
*/
-
class RedisentCluster {
-
-
/**
-
* Collection of Redisent objects attached to Redis servers
-
* @var array
-
* @access private
-
*/
-
private $redisents;
-
-
/**
-
* Aliases of Redisent objects attached to Redis servers, used to route commands to specific servers
-
* @see RedisentCluster::to
-
* @var array
-
* @access private
-
*/
-
private $aliases;
-
-
/**
-
* Hash ring of Redis server nodes
-
* @var array
-
* @access private
-
*/
-
private $ring;
-
-
/**
-
* Individual nodes of pointers to Redis servers on the hash ring
-
* @var array
-
* @access private
-
*/
-
private $nodes;
-
-
/**
-
* Number of replicas of each node to make around the hash ring
-
* @var integer
-
* @access private
-
*/
-
private $replicas = 128;
-
-
/*** 特殊方法默认到特定连接
-
* The commands that are not subject to hashing
-
* @var array
-
* @access private
-
*/
-
private $dont_hash = array(
-
\'RANDOMKEY\', \'DBSIZE\',
-
\'SELECT\', \'MOVE\', \'FLUSHDB\', \'FLUSHALL\',
-
\'SAVE\', \'BGSAVE\', \'LASTSAVE\', \'SHUTDOWN\',
-
\'INFO\', \'MONITOR\', \'SLAVEOF\'
-
);
-
-
/**
-
* Creates a Redisent interface to a cluster of Redis servers
-
* @param array $servers The Redis servers in the cluster. Each server should be in the format array(\'host\' => hostname, \'port\' => port)
-
*/
-
function __construct($servers) {
-
$this->ring = array();
-
$this->aliases = array();
-
foreach ($servers as $alias => $server) {
-
$this->redisents[] = new Redisent($server[\'host\'], $server[\'port\']);
-
if (is_string($alias)) {
-
$this->aliases[$alias] = $this->redisents[count($this->redisents)-1];
-
}
-
for ($replica = 1; $replica <= $this->replicas; $replica++) {
-
$this->ring[crc32($server[\'host\'].\':\'.$server[\'port\'].\'-\'.$replica)] = $this->redisents[count($this->redisents)-1];
-
}
-
}
-
ksort($this->ring, SORT_NUMERIC);
-
$this->nodes = array_keys($this->ring);
-
}
-
-
/**
-
* Routes a command to a specific Redis server aliased by {$alias}.
-
* @param string $alias The alias of the Redis server
-
* @return Redisent The Redisent object attached to the Redis server
-
*/
-
function to($alias) {
-
if (isset($this->aliases[$alias])) {
-
return $this->aliases[$alias];
-
}
-
else {
-
throw new Exception(\"That Redisent alias does not exist\");
-
}
-
}
-
-
/* Execute a Redis command on the cluster */
-
function __call($name, $args) {
-
-
/* Pick a server node to send the command to */
-
$name = strtoupper($name);
-
if (!in_array($name, $this->dont_hash)) {
-
$node = $this->nextNode(crc32($args[0]));
-
$redisent = $this->ring[$node];
-
}
-
else {
-
$redisent = $this->redisents[0];
-
}
-
-
/* Execute the command on the server */
-
return call_user_func_array(array($redisent, $name), $args);
-
}
-
-
/*** 2分法查找
-
* Routes to the proper server node
-
* @param integer $needle The hash value of the Redis command
-
* @return Redisent The Redisent object associated with the hash
-
*/
-
private function nextNode($needle) {
-
$haystack = $this->nodes;
-
while (count($haystack) > 2) {
-
$try = floor(count($haystack) / 2);
-
if ($haystack[$try] == $needle) {
-
return $needle;
-
}
-
if ($needle < $haystack[$try]) {
-
$haystack = array_slice($haystack, 0, $try + 1);
-
}
-
if ($needle > $haystack[$try]) {
-
$haystack = array_slice($haystack, $try + 1);
-
}
-
}
-
return $haystack[count($haystack)-1];
-
}
-
-
}
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/26477398/viewspace-1258943/
,如需转载,请注明出处,否则将追究法律责任。