当前位置: 首页 > article >正文

murmur 算法

简介

MurmurHash是一种高效的非加密哈希函数,适用于哈希表中的一般哈希任务。
MurmurHash的名称来源于Murmur,意为一种低频的声音,体现了其设计的低碰撞率和高性能。
名称来自两个基本操作,乘法(MU)和旋转(R),在其内部循环中使用。与其它流行的哈希函数相比,对于规律性较强的key,MurmurHash的随机分布特征表现更良好。
MurmurHash与加密散列函数不同,它不是专门设计为难以被对手逆转,因此不适用于加密目的。它常被应用于分布式系统,很多开源项目如Kafka、Redis,Memcached,Cassandra,HBase,Elasticsearch等等都使用它。
MurmurHash的当前的版本是MurmurHash3,能够产生出32-bit或128-bit哈希值。

优点和缺点

速度快,比安全散列算法快几十倍;
变化足够激烈,相似的字符串如“abc”和“abd”能够均匀散落在哈希环上;
高熵:确保输入的微小变化会显著改变输出,减少碰撞。
高性能:利用简单的位操作和混合步骤,适用于现代处理器。
确定性:相同的输入总是生成相同的输出。

不保证安全性(缺点)

算法原理

以MurmurHash3_x86_32为例,它适用于32位系统,并输出32位的哈希值。下面是MurmurHash3的主要步骤:

初始化

设置一个种子(seed)值,用于初始化哈希值。这样可以通过不同的种子来生成不同的哈希值。

处理块(chunks)

输入数据被分成固定大小的块(通常为4 bytes)。每个块使用一次哈希函数。
对于每个块,首先将它们视为32位整数。

混合过程:

对每个32位块进行一系列位操作,包括乘法、左移和右移。这些操作用来混合位,使得输入的不同位对最终哈希值有较大的影响。
具体的混合步骤如下:

k *= c1;
k = rotl32(k, r1);
k *= c2;
h ^= k;
h = rotl32(h, r2);
h = h * m + n;

c1, c2, r1, r2, m, n是固定的常数,通过实验选择,使得哈希函数具有良好的分布性和随机性。

处理尾部(tail)

如果输入数据的长度不是块大小的倍数,剩余的未处理字节(称为尾部)也会影响最终哈希值。
对尾部的字节进行类似的混合处理,但处理量要少得多

最终化(finalization)

h ^= h >> 16;
h *= 0x85ebca6b;
h ^= h >> 13;
h *= 0xc2b2ae35;
h ^= h >> 16;

Demo

#include <stdio.h>
#include <stdint.h>
#include <string.h>

#define ROTL32(x, r) ((x << r) | (x >> (32 - r)))

uint32_t MurmurHash3_x86_32(const void *key, int len, uint32_t seed) {
    const uint8_t *data = (const uint8_t *)key;
    const int nblocks = len / 4;
    uint32_t h1 = seed;
    
    const uint32_t c1 = 0xcc9e2d51;
    const uint32_t c2 = 0x1b873593;

    // Body
    const uint32_t *blocks = (const uint32_t *)(data + nblocks * 4);
    for (int i = -nblocks; i; i++) {
        uint32_t k1 = blocks[i];

        k1 *= c1;
        k1 = ROTL32(k1, 15);
        k1 *= c2;

        h1 ^= k1;
        h1 = ROTL32(h1, 13);
        h1 = h1 * 5 + 0xe6546b64;
    }

    // Tail
    const uint8_t *tail = (const uint8_t *)(data + nblocks * 4);
    uint32_t k1 = 0;

    switch (len & 3) {
    case 3:
        k1 ^= tail[2] << 16;
    case 2:
        k1 ^= tail[1] << 8;
    case 1:
        k1 ^= tail[0];
        k1 *= c1;
        k1 = ROTL32(k1, 15);
        k1 *= c2;
        h1 ^= k1;
    }

    // Finalization
    h1 ^= len;
    h1 ^= h1 >> 16;
    h1 *= 0x85ebca6b;
    h1 ^= h1 >> 13;
    h1 *= 0xc2b2ae35;
    h1 ^= h1 >> 16;

    return h1;
}

int main() {
    const char *key = "Hello, World!";
    uint32_t seed = 42;  // A random seed value
    uint32_t hash = MurmurHash3_x86_32(key, strlen(key), seed);

    printf("Hash of '%s' with seed %u is: %u\n", key, seed, hash);
	/* Hash of 'Hello, World!' with seed 42 is: 1794106050 */
    return 0;
}

http://www.kler.cn/a/314652.html

相关文章:

  • Centos安装Elasticsearch教程
  • PNG图片批量压缩exe工具+功能纯净+不改变原始尺寸
  • HTTP 客户端怎么向 Spring Cloud Sleuth 传输跟踪 ID
  • Diffusion Policy——斯坦福机器人UMI所用的扩散策略:从原理到其编码实现(含Diff-Control、ControlNet详解)
  • 基于碎纸片的拼接复原算法及MATLAB实现
  • flutter下拉刷新上拉加载的简单实现方式三
  • MySQL(日志)
  • 未来视界,触手可及:bigmp4 引领 AI 视频处理新革命
  • pytorch的动态计算图机制
  • 华为HarmonyOS地图服务 4 - 通过“地图相机“控制地图的可见区域
  • C语言中易混淆概念的关键字
  • Vue+nodejs+express旅游景区门票预订网站的设计与实现 8caai前后端分离
  • MyBatis操作数据库-XML实现
  • MySQL5.7主从复制集群如何配置半同步复制
  • asp.net core调用wps实现word转pdf的方法
  • Python Selenium 自动化爬虫 + Charles Proxy 抓包
  • 十四,在Spring Boot当中对应“ Tomcat 服务器的相关配置”和“服务器的切换”的详细说明
  • 掌握 JavaScript 中的函数表达式
  • 页面布局实现-左侧横向滑动展示隐藏数据,右侧固定展示操作按钮。可上下滑动联动
  • 常用的图像增强的算法之间的联系和区别
  • Python3网络爬虫开发实战(17)爬虫的管理和部署(第一版)
  • Samba服务
  • 传统到AI 大数据分析的演变,颠覆智慧水电的未来?
  • 【JavaEE初阶】多线程(4)
  • 2024/9/21黑马头条跟学笔记(十)
  • Ubuntu 安装和使用 Fcitx 中文输入法;截图软件flameshot