一致性hash算法-php-redis版本

8 篇文章 0 订阅
<?php
//抄过来的代码,改了一点点,
//实际来说,效率偏低,命中还算均匀

 class RedisHash {

	private $_node = array();
	private $_nodeData = array();
	private $_keyNode = 0;
	private $_redis = null;
	public  $nodeCounter=[];
	
	//每个物理服务器生成虚拟节点个数 [注:节点数越多,cache分布的均匀性越好,
	//同时set get操作时,也更耗资源,10台物理服务器,采用200较为合理]
	private $_virtualNodeNum = 100;
	
	private function __construct() {
	       
		$config = [
			'127.0.0.1:6370',
			'127.0.0.1:6371',
			'127.0.0.1:6372',
			'127.0.0.1:6373',
			'127.0.0.1:6374',
			'127.0.0.1:6375',
			'127.0.0.1:6376',
			'127.0.0.1:6377',
			'127.0.0.1:6378',
			'127.0.0.1:6379',
		];				       
		if (!$config) throw new Exception('Cache config NULL');
		
		foreach ($config as $key => $value) {
			for ($i = 0; $i < $this->_virtualNodeNum; $i++) {
				$this->_node[sprintf("%u", crc32($value . '_' . $i))] = $value . '_' . $i;
			}
		}
		ksort($this->_node);
	}

	private function __clone(){}
	
	
	static public function getInstance() {
		static $redisObj = null;
		if (!is_object($redisObj)) {
			$redisObj = new self();
		}
		return $redisObj;
	}
	
	
	public function getRedis($key) {
		$this->_nodeData = array_keys($this->_node);
		$this->_keyNode = sprintf("%u", crc32($key));
		$nodeKey = $this->_findServerNode();		
		//如果超出环,从头再用二分法查找一个最近的,然后环的头尾做判断,取最接近的节点
		if ($this->_keyNode > end($this->_nodeData)) {
			$this->_keyNode -= end($this->_nodeData);
			$nodeKey2 = $this->_findServerNode();
			if (abs($nodeKey2 - $this->_keyNode) < abs($nodeKey - $this->_keyNode))  $nodeKey = $nodeKey2;
		}
		
		// var_dump($this->_node[$nodeKey]);
		
		list($config, $num) = explode('_', $this->_node[$nodeKey]);
		if (!$config) throw new Exception('Cache config Error');
		if (!isset($this->_redis[$config])) {
			$this->_redis[$config] = new \Redis;
			list($host, $port) = explode(':', $config);
			$this->_redis[$config]->connect($host, $port);	
		}
		
		$this->nodeCounter[$config] ++;
		
		return $this->_redis[$config];
	}
	
	
	private function _findServerNode($m = 0, $b = 0) {
	    $total = count($this->_nodeData);
	    if ($total != 0 && $b == 0) $b = $total - 1;
	    if ($m < $b){
			$avg = (int)(($m+$b) / 2);
			if ($this->_nodeData[$avg] == $this->_keyNode) {
				return $this->_nodeData[$avg];
			}elseif ($this->_keyNode < $this->_nodeData[$avg] && ($avg-1 >= 0)) {
				return $this->_findServerNode($m, $avg-1);
			}else {
				return $this->_findServerNode($avg+1, $b);
			}
	    }
		if (abs($this->_nodeData[$b] - $this->_keyNode) < abs($this->_nodeData[$m] - $this->_keyNode))  return $this->_nodeData[$b];
		else return $this->_nodeData[$m];
	}
		
	public function set($key, $value, $expire = 0) {
	    return $this->getRedis($key)->set($key, $value,$expire);
	}
	
	
	public function get($key) {
		return $this->getRedis($key)->get($key);
	}
	
	public function delete($key) {
		return $this->getRedis($key)->delete($key);
	}
	
}

$time_start = microtime(true);
$redis = RedisHash::getInstance();
for($i=0;$i<10000;$i++) {
     $b = $redis->set('m_key'.$i, $i);
}
print_r($redis->nodeCounter);
echo  microtime( true ) - $time_start ;   



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: Redis一致性哈希是一种分布式算法,用于解决在缓存系统中增加或减少实例时可能出现的缓存击穿和缓存雪崩问题。这种算法使用哈希函数将整个哈希值空间组织成一个虚拟的圆环,将不同的缓存数据映射到圆环上的不同位置。具体而言,Redis实例的个数可能会发生变化,当增加或减少实例时,映射关系就会改变,导致大量的Redis请求找不到对应的实例。而一致性哈希算法通过对232取模的方式,将哈希值映射到圆环上的位置,从而实现了负载均衡和缓存数据的一致性存储。相比传统的取模操作,一致性哈希算法能够更好地应对增减Redis实例的情况,提高缓存命中率。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [Redis-Hash一致性算法](https://blog.csdn.net/WangLi1201/article/details/79270073)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [Redis一致性Hash算法](https://blog.csdn.net/qq_21125183/article/details/90019034)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [Redis 一致性哈希](https://blog.csdn.net/m0_54921756/article/details/125987939)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值