Looyao's Blog

记录一些点滴

PHP: 分布均匀的hash函数

| Comments

前几天google了一些php的hash函数, 想找到一种分布较为均匀的hash算法, 这样对于比如数据库分表或者其他一些需要hash的场景比较有帮助. 然后就发现了这个Another happy memcached user.

很多hash函数采用times 33, 下边是php的实现:

1
2
3
4
5
6
7
8
9
function hash_func1($key, $n)
{
    $hash = 0;
    for ($i = 0; $i < strlen($key); $i++) {
        $hash = $hash * 33 + ord($key[$i]);
    }

    return $hash % $n;
}

而上边链接的邮件中提到了一种分布更均匀的算法, 如下:

1
2
3
4
5
function hash_func(&$keyword, $n)
{
    $hash = crc32($keyword) >> 16 & 0x7fff;
    return $hash % $n;
}

为了自己验证下, 我整理了一套cet-4词汇表来做测试. 测试结果如下, 使用time 33

bash$ time php h.php
bucket(0): 11.33%
bucket(1): 9.61%
bucket(2): 10.23%
bucket(3): 9.77%
bucket(4): 9.85%
bucket(5): 9.81%
bucket(6): 10.21%
bucket(7): 9.50%
bucket(8): 9.70%
bucket(9): 9.99%

real    0m0.026s
user    0m0.006s
sys 0m0.003s

使用crc32移位的这个,

bash$ time php h.php
bucket(0): 10.16%
bucket(1): 10.52%
bucket(2): 9.72%
bucket(3): 9.79%
bucket(4): 9.54%
bucket(5): 10.34%
bucket(6): 9.21%
bucket(7): 10.45%
bucket(8): 10.12%
bucket(9): 10.14%

real    0m0.015s
user    0m0.003s
sys 0m0.002s

从测试结果来看, 使用crc32移位的hash方法要比times 33分布更为均匀一些, 并且效率也要高一些. 测试的php代码和cet4词汇表: 点击这里下载. 感兴趣的可以自己测试一下.

Comments