murmurhash3算法的go语言实现

MurmurHash的定义

MurmurHash 是一种非加密型哈希函数,适用于一般的哈希检索操作。由Austin Appleby在2008年发明,并出现了多个变种,都已经发布到了公有领域(public domain)。与其它流行的哈希函数相比,对于规律性较强的key,MurmurHash的随机分布特征表现更良好。

MurmurHash的特点

  • 高速度: MurmurHash3 被设计为快速计算哈希值,特别适用于需要高性能的场景。它的实现通常使用了有效的位运算和数值操作,以确保在处理大量数据时仍能保持高效率。
  • 低碰撞: MurMurHash3 128 位版本哈希值是 128 位的,在数据量只有千万级别的情况下,基本不用担心碰撞。
  • 良好的分布性: MurmurHash3 提供了良好的随机性和分布特性。这意味着不同的输入数据在哈希后,其哈希值分布均匀,减少了哈希冲突的可能性。这对于哈希表、散列数据结构等需要快速检索的应用至关重要。
  • 适用性广泛: 由于其速度和分布性,MurmurHash3 可以应用于各种场景,包括分布式系统、缓存系统、数据检验和索引等。它在这些领域中可以提供快速且有效的哈希功能。
  • 可配置性: MurmurHash3 允许用户通过调整种子值和其他参数来定制哈希算法的行为。这种灵活性使得可以根据具体需求进行优化,例如调整哈希长度或者初始化种子值,以适应不同的应用场景和数据集合。
  • 非加密性: MurmurHash3 是一种非加密的哈希函数,它专注于提供高速和良好的分布特性,但不适用于需要强加密保护的数据传输或存储场景。对于这类需求,应使用专门的加密哈希函数。

MurmurHash3的实现原理

初始化参数

  • 种子值(Seed): MurmurHash3 使用一个种子值(seed),这个种子值可以用来初始化哈希计算的状态。不同的种子值将产生不同的哈希结果,这对于哈希表的冲突处理很有用。
  • 常数: 算法中使用一些预定义的常数,这些常数有助于确保哈希的混合和扩散性。

主循环

主循环是 MurmurHash3 哈希计算的核心部分,通常包括以下步骤:

按 4 字节处理数据: 将输入数据按 4 字节(32 位)一组进行处理。如果最后一个块不足 4 字节,则使用特殊处理方式。

混合(Mixing)操作: 对每个 4 字节的块进行混合操作,以确保输入数据的高低位均匀地分布到输出哈希值中。这通常涉及位运算、乘法、异或等操作。

旋转(Rotation)和混合: MurmurHash3 使用了一些位级操作和旋转操作,以增加哈希的随机性和分散性。

最终化

在处理完所有输入数据后,对哈希值进行最终化操作。这些操作通常包括最后一次混合、再次使用常数和种子值进行混合,以确保最终的哈希值具有良好的随机性和分布性。

输出

最终得到的哈希值是一个固定长度(通常是 32 位或 64 位)的整数,可以作为输入数据的唯一标识或索引值使用。

MurmurHash的Go语言实现

const (
	c1 = 0xcc9e2d51
	c2 = 0x1b873593
	r1 = 15
	r2 = 13
	m  = 5
	n  = 0xe6546b64
)

func MurmurHash3(key []byte, seed uint32) uint32 {
	var h1 = seed
	var k1 uint32
	var chunk uint32

	blocks := len(key) / 4

	for i := 0; i < blocks; i++ {
		chunk = uint32(key[i*4]) | uint32(key[i*4+1])<<8 | uint32(key[i*4+2])<<16 | uint32(key[i*4+3])<<24

		k1 = chunk
		k1 *= c1
		k1 = bits.RotateLeft32(k1, r1)
		k1 *= c2

		h1 ^= k1
		h1 = bits.RotateLeft32(h1, r2)
		h1 = h1*m + n
	}

	tail := key[blocks*4:]
	switch len(tail) {
	case 3:
		h1 ^= uint32(tail[2]) << 16
		fallthrough
	case 2:
		h1 ^= uint32(tail[1]) << 8
		fallthrough
	case 1:
		h1 ^= uint32(tail[0])
		h1 *= c1
		h1 = bits.RotateLeft32(h1, r1)
		h1 *= c2
	}

	h1 ^= uint32(len(key))

	h1 ^= h1 >> 16
	h1 *= 0x85ebca6b
	h1 ^= h1 >> 13
	h1 *= 0xc2b2ae35
	h1 ^= h1 >> 16

	return h1
}

func main() {
	s := "video/BV1yT4y1a7tD/?spm_id_from=333.337.search-card.all.click&vd_source=3cd3e5853cdff0baa992698bfe4286f6"
	//转换为byte类型
	arrayOfString := []byte(s)
	resultTen := MurmurHash3(arrayOfString, 0)
	fmt.Println(resultTen)
}

代码解析

常量定义

  • c1, c2: 用于混合和乘法的常数。
  • r1, r2: 用于左移位操作的位移量。
  • m, n: 用于混合操作的常数。

MurmurHash3函数

  • MurmurHash3函数接受两个参数:key是待哈希的字节数组,seed是哈希种子,用于初始化哈希值。
  • h1 是哈希结果的中间值,初始化为seed。
  • k1 是每个处理的块的哈希键。
  • chunk 是每次处理的四个字节的数据块。

哈希计算过程

处理数据:

  • 将输入的字节数组分成4字节的块,按顺序处理。
  • 计算每个块的哈希键 k1,应用一系列乘法、位移和异或操作。
  • 将结果与中间值 h1 进行混合和旋转操作。
  • 处理剩余不足4字节的部分(尾部):

处理剩余尾部:

如果输入的字节数组长度不是4的整数倍,处理剩余的部分。这部分通过一系列的位移、乘法和异或操作来处理,确保整个字节数组都被考虑在内。

最终对哈希值进行最后的混合和压缩,确保输出的哈希值分布均匀和具有良好的性质。

  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值