InitPHP (A PHP Framework) 用户手册
第6章 6.7.9 一致性Hash

接口描述:

一致性Hash类。属于InitPHP框架扩展类,需要通过$this->getLibrary()方法获取

使用方法:

$hash = $this->getLibrary('hash'); 

实例:

$hash = $this->getLibrary('hash'); 
//添加node节点,10代表虚拟节点个数,虚拟节点数目越大,hash分布越均匀 
//为了控制hash效率,将固定节点值存放在hash_table.php文件里面 
//类文件中有2个参数可以配置 //private $is_init = 1; 
//hash_table初始化-0关闭,1开启,当初始化完毕之后,关闭该功能 
//private $filename = 'data/hash_table.php'; 
//hash_table缓存路径 
$hash->add_node(array('192.168.1.1', '192.168.1.2', '192.168.1.3'), 10); 
//获取key值对应的一致性hash_table上的node节点 echo $hash->get_node('woshishen'); 
//输出192.168.1.3,说明该key分布式这个服务器上
echo $hash->get_node('woshishen'); //输出192.168.1.3,说明该key分布式这个服务器上

具体类:

if (!defined('IS_INITPHP')) exit('Access Denied!');   
/*********************************************************************************
 * InitPHP 2.1 国产PHP开发框架  扩展类库-一致性HASH
 *-------------------------------------------------------------------------------
 * 版权所有: CopyRight By initphp.com
 * 您可以自由使用该源码,但是在使用过程中,请保留作者信息。尊重他人劳动成果就是尊重自己
 *-------------------------------------------------------------------------------
 * $Author:zhuli
 * $Dtime:2011-10-09 
***********************************************************************************/ 
class hashInit {

	private static $hash_table = array(); //hash_table,存放hash对应值
	private static $hash_list = array(); //存放值
	private $is_init = 1; //hash_table初始化-0关闭,1开启,当初始化完毕之后,关闭该功能
	private $filename = 'data/hash_table.php'; //hash_table缓存路径
	
	/**
	 *	一致性hash:添加节点
	 *  只有当且仅当开启is_init初始化hash_table的时候
	 *  hash_table文件才会生成
	 *  @param  string  $node    字符串
	 *  @param  string  $num     虚拟节点
	 *  @return int 
	 */
	public function add_node($node, $num = 0) { 
		if ($this->is_init == 1) {
			if (is_array($node)) { 
				foreach ($node as $string) {
					$key = $this->hash_md5($string);
					self::$hash_table[$this->hash_crc($key)] = array(
						$key, 
						$string
					);
					$this->add_virtual_node($string, $num);
					self::$hash_list[] = $this->hash_crc($key);
				}
				sort(self::$hash_list);
			}
			$table = '$hash_table = ' . var_export(self::$hash_table, TRUE) . ';';
			$list = '$hash_list = ' . var_export(self::$hash_list, TRUE);
			$value = '';
			@file_put_contents($this->filename, $value);
		}
		return true;
	}
	
	/**
	 *	一致性hash:获取hash对应的节点值
	 *  @param  string  $node    字符串
	 *  @return int
	 */
	public function get_node($string) {
		$key     = $this->hash_md5($string);
		$key_val = $this->hash_crc($key);
		$result = $start = 0;
		if (empty(self::$hash_table) && empty(self::$hash_list)) {
			include_once($this->filename);
			self::$hash_table = $hash_table;
			self::$hash_list  = $hash_list;
		}
		foreach (self::$hash_list as $val) {
			if ($start == 0) $result = $val;
			if ($key_val < $val) {
				$result = $val;
				break;
			} 
			$start = 1; 
		}
		return self::$hash_table[$result][1];
	}
	
	/**
	 *	一致性hash:生成虚拟节点
	 *  @param  string  $string  字符串
	 *  @param  string  $num     虚拟节点
	 *  @return int
	 */
	public function add_virtual_node($string, $num) {
		$num = (int) $num;
		if ($num < 1) return false;
		for ($i=0; $i<$num; $i++) {
			$key = $this->hash_md5($string . '#' . $i);
			self::$hash_table[$this->hash_crc($key)] = array($key, $string);
			self::$hash_list[] = $this->hash_crc($key);
		}
	}

	/**
	 *	一致性hash,计算一个字符串的 crc32 多项式
	 *  @param  string  $string  字符串
	 *  @return int
	 */
	private function hash_crc($string) {
		return crc32($string);
	}
	
	/**
	 *	一致性hash:MD5加密得到KEY值
	 *  @param  string  $string  字符串
	 *  @return int
	 */
	private function hash_md5($string) {
		return md5($string);
	}
}