美文网首页
PHP 实现普通hash和一致性hash

PHP 实现普通hash和一致性hash

作者: 天上掉下的胖纸 | 来源:发表于2020-04-28 10:11 被阅读0次

1. 普通hash实现代码

class CommonHash
{
    protected $_ser = [];
    protected $_num = 0;

    public function _hash($str)
    {
        return sprintf("%u", crc32($str));
    }

    public function lookup($key)
    {
        $index = $this->_hash($key) % 4;
        return $this->_ser[$index];
    }

    public function addNode($s)
    {
        $this->_ser[] = $s;
        $this->_num += 1;
    }

    public function delNode($s)
    {
        foreach ($this->_ser as $k => $v) {
            if ($s == $v) {
                unset($this->_ser[$k]);
                $this->_num -= 1;
            }
        }
    }
}

//测试
$commonHash = new CommonHash();
$commonHash->addNode("a");
$commonHash->addNode("b");
$commonHash->addNode("c");
$commonHash->addNode("d");

for ($i = 1; $i < 100; $i++) {
    echo "serv : " . $commonHash->lookup("key:" . $i) . "\n";
}

2. 一致性hash实现代码


class ConsistentHash
{
    protected $nodes = []; //服务节点
    protected $points = []; //虚拟节点的数组
    protected $mul = 64; //每个节点做出64个虚拟节点


    public function _hash($str)
    {
        return sprintf("%u", crc32($str));
    }

    public function lookup($key)
    {
        //重置数组指针,好像是个坑...哈哈哈
        reset($this->points);
        $nodePoint = key($this->points); //默认等于第一个point

        $keyPoint = $this->_hash($key);
        foreach ($this->points as $point => $node) {
            if ($keyPoint <= $point) {
                $nodePoint = $point;
                break;
            }
        }
        return $this->points[$nodePoint];
    }

    public function addNodes($node)
    {
        $this->nodes[$node] = [];
        for ($i = 0; $i < $this->mul; $i++) {
            $key = md5($node . "_" . $i);
            $point = $this->_hash($key); //计算hash值
            $this->points[$point] = $node; //放入虚拟节点中, 虚拟节点的node节点
            $this->nodes[$node][] = $point; //node节点下哪些虚拟节点
        }
        $this->resort();
    }

    public function delNode($node)
    {
        foreach ($this->points as $point => $no) {
            if ($no == $node) {
                unset($this->points[$point]);
            }
        }
        unset($this->nodes[$node]);
        $this->resort();
    }

    //给虚拟节点排序
    public function resort()
    {
        ksort($this->points);
    }


}

//测试一下.发现,随着服务器的台数增加,节点可能落到别的服务器上,不是始终定死到一台服务器的, 一般情况下问题不大
$consistentHash = new ConsistentHash();
for ($i = 0; $i < 6; $i++) {
    $consistentHash->addNodes("A{$i}");
    $consistentHash->addNodes("B{$i}");
    $consistentHash->addNodes("C{$i}");
    $consistentHash->addNodes("D{$i}");
    $consistentHash->addNodes("E{$i}");
    $consistentHash->addNodes("F{$i}");
    $consistentHash->addNodes("G{$i}");
    $consistentHash->addNodes("H{$i}");
    $consistentHash->addNodes("I{$i}");
}
$node = $consistentHash->lookup("woshishui");

print_r($node);

相关文章

网友评论

      本文标题:PHP 实现普通hash和一致性hash

      本文链接:https://www.haomeiwen.com/subject/hcomwhtx.html