如何在PHP7.2中生成64位杂音哈希v2?

50pmv0ei  于 2021-06-20  发布在  Mysql
关注(0)|答案(1)|浏览(339)

我有一个mysql数据库,它有一些杂音2散列(作为无符号的64位整数),这些杂音是用percona udf生成的,percona udf是mysql数据库的percona串在这里找到的https://github.com/percona/build-test/blob/master/plugin/percona-udf/murmur_udf.cc
我的问题是,现在我需要在php端生成这些相同的散列,但是我似乎无法找到或调整任何现有的东西来为相同的输入工作/输出相同的输出。
我尝试过的事情:
将percona udf中的c函数复制到最初生成32位int散列的php扩展的分叉版本中https://github.com/stirlingmarketinggroup/php_murmurhash. 这几乎奏效了,就像在它编译的时候一样,但是当我在php中执行这个函数时,apache服务器会因为一个segfault而崩溃,而且我对c和php扩展不够熟悉,无法调试它
这个错误是由我运行这个函数引起的

var_dump(murmurhash('Hello World'));

当我下载的时候它正常工作https://github.com/kibae/php_murmurhash (原始的、32位的、产生散列的扩展名)并按照说明操作,但是一旦我替换了函数(只在hurrushash2.cpp文件中编辑https://github.com/stirlingmarketinggroup/php_murmurhash/blob/master/murmurhash2.cpp)同一个函数调用会使php脚本崩溃。
尝试将percona udf c函数移植到php。我不确定我的php函数是否100%准确地解释了指针递增的原因,但我怀疑更多的原因是,我在php版本中得到完全不同的输出与php不支持无符号整数有关。
下面是我作为percona c
函数的端口编写的php函数

function murmurhash2(string $s) : int {
    $len = strlen($s);
    $seed = 0;

    $m = 0x5bd1e995;
    $r = 24;

    $h1 = $seed ^ $len;
    $h2 = 0;

    $i = 0;

    while ($len >= 8) {
        $k1 = ord($s[$i++]);
        $k1 *= $m; $k1 ^= $k1 >> $r; $k1 *= $m;
        $h1 *= $m; $h1 ^= $k1;
        $len -= 4;

        $k2 = ord($s[$i++]);
        $k2 *= $m; $k2 ^= $k2 >> $r; $k2 *= $m;
        $h2 *= $m; $h2 ^= $k2;
        $len -= 4;
    }

    if ($len >= 4) {
        $k1 = ord($s[$i++]);
        $k1 *= $m; $k1 ^= $k1 >> $r; $k1 *= $m;
        $h1 *= $m; $h1 ^= $k1;
        $len -= 4;
    }

    switch ($len) {
        case 3: $h2 ^= ord($s[2]) << 16;
        case 2: $h2 ^= ord($s[1]) << 8;
        case 1: $h2 ^= ord($s[0]);
                $h2 *= $m;
    };

    $h1 ^= $h2 >> 18; $h1 *= $m;
    $h2 ^= $h1 >> 22; $h2 *= $m;
    $h1 ^= $h2 >> 17; $h1 *= $m;

    $h = $h1;

    $h = ($h << 32) | $h2;
    return $h;
}

在mysql中我得到了这个

select murmur_hash('Hello World'), cast(murmur_hash('Hello World')as unsigned), CONV(cast(murmur_hash('Hello World')as unsigned), 10, 16);
-- -8846466548632298438 9600277525077253178 853B098B6B655C3A

在php中我得到

var_dump(murmurhash2('Hello World'));
// int(5969224437940092928)

所以看看mysql和php结果,无论是有符号的还是无符号的都与我的php输出不匹配。
有什么东西可以用我前面的两种方法中的任何一种来修复,或者我可以用一种已经在工作的方法来代替吗?

svujldwt

svujldwt1#

我已经通过将percona散列函数直接移植到php扩展mysql中解决了这个问题。
安装和使用说明张贴在这里https://github.com/stirlingmarketinggroup/php-murmur-hash

示例输出

在mysql中,percona扩展的用法如下

select`murmur_hash`('Yeet')
-- -7850704420789372250

在php中

php -r 'echo murmur_hash("Yeet");'
// -7850704420789372250

请注意,对于这两种环境,这些都被视为有符号整数,您可以在mysql中使用 cast(murmur_hash('Yeet')as unsigned) ,但php不支持无符号整数。

相关问题