redis一致性hash

Mar 15, 2017


####

分布式缓存部署方案

当有1台cache服务器不能满足我们的需求,我们需要布置多台来做分布式服务器,但是 有个问题,怎么确定一个数据应该保存到哪台服务器上呢?

有两种方案,第一种普通hash分布,第二种一致性哈希分布

普通hash分布 首先将key处理为一个32位字符串,取前8位,在经过hash计算处理成整数并返回,然后映射到其中一台服务器 $servers[mhash($key) % 2] 这样得到其中一台服务器的配置,利用这个配置完成分布式部署

在服务器数量不发生变化的情况下,普通hash分布可以很好的运作,当服务器的数量发生变化,问题就来了

试想,增加一台服务器,同一个key经过hash之后,与服务器取模的结果和没增加之前的结果肯定不一样,这就导致了,之前保存的数据丢失

一致性哈希算法

原理详细可见 http://blog.csdn.net/u014490157/article/details/52244378

优点:在分布式的cache缓存中,其中一台宕机,迁移key效率最高 将服务器列表进行排序,根据mHash($key) 匹配相邻服务器

php一致性hash类下载地址:flexihash


include ("../FlexiHash.php");
		
class MipRedis
{

    public static $redisCluster = [];

    public static function cluster()
    {
        $codisConfig = include ("../config.php");
        // redis_id
        $redis_id = self::selectRedis($codisConfig, $user_id);
        $host = $codisConfig[$redis_id]['host'];
        $port = $codisConfig[$redis_id]['port'];
        $redisKey = md5($host.":".$port);

        // 连接Redis
        if (!isset(self::$redisCluster[$redisKey]))
        {
            $redis = new \Redis();
            $redis->connect($codisConfig[$redis_id]['host'], $codisConfig[$redis_id]['port']);
            self::$redisCluster[$redisKey] = $redis;
        }
        
        return self::$redisCluster[$redisKey];
    }

    public static function selectRedis( $codisConfig = [], $user_id = 0 )
    {
        $num = count($codisConfig);
        $hash_id = self::getHash($user_id, $num);
        $redis_id = $hash_id % $num;
        return $redis_id;
    }

    public static function getHash( $user_id = 0 , $num )
    {
        $hash = new FlexiHash();
        $targets = [];
        for($i=0; $i<$num; $i++)
        {
            $targets[] = $i;
        }
        $hash->addTargets( $targets);
        $hashValue = $hash->lookup( $user_id );
        return $hashValue;
    }

}