哈希MurmurHash算法详解

专利法实施细则哈希MurmurHash算法详解
⽂章⽬录
MurmurHash:(multiply and rotate) and (multiply and rotate) Hash,乘法和旋转的hash 算法。
⼀、哈希函数
定义
散列函数(英语:Hash function)⼜称散列算法、哈希函数,是⼀种从任何⼀种数据中创建⼩的数字“指纹”的⽅法。散列函数把消息或数据压缩成摘要,使得数据量变⼩,将数据的格式固定下来。该函数将数据打乱混合,重新创建⼀个叫做散列值(hash values,hash codes)的指纹。散列值通常⽤⼀个短的随机字母和数字组成的字符串来代表。好的散列函数在输⼊域中很少出现散列冲突。
特点
加密:加密存在数据库中的密码(password)字符串,由于散列算法所计算出来的散列值(Hash Value)具有不可逆(⽆法逆向演算回原本的数值)的性质,因此可有效的保护密码。
压缩:把任意长度的输⼊通过散列算法变换成固定长度的输出。
应⽤
保护资料、确保传递真实的信息、散列表、错误校正、语⾳识别、信息安全。。。
常见哈希算法
MD系列(MD5)、SHA系列(SHA-1)、CRC,甚⾄JDK hashCode()也是哈希算法的⼀种。可以将他们分成三代:
第⼀代:SHA-1(1993),MD5(1992),CRC(1975),Lookup3(2006)
第⼆代:MurmurHash(2008)
第三代:CityHash, SpookyHash(2011)
分类可分为加密型、⾮加密型:
加密型:MD系列(MD5)、SHA系列(SHA-1)
⾮加密型:CRC、MurmurHash
这⾥记录⼀下在第⼆代中⼏乎⼀统江湖的MurmurHash。
⼆、murmurhash
定义
MurmurHash 是⼀种⾮加密型哈希函数,适⽤于⼀般的哈希检索操作。由Austin Appleby在2008年发明,并出现了多个变种,都已经发布到了公有领域(public domain)。与其它流⾏的哈希函数相⽐,对于规律性较强的key,MurmurHash的随机分布特征表现更良好。
特点
1.快。
MurMurHash3 ⽐ MD5 快。
2.低碰撞
MurMurHash3 128 位版本哈希值是 128 位的,跟 MD5 ⼀样。128 位的哈希值,在数据量只有千万级别的情况下,基本不⽤担⼼碰撞。
3.⾼混淆。
散列值⽐较“均匀”,如果⽤于哈希表,布隆过滤器等, 元素就会均匀分布。
应⽤
⼴泛应⽤于各开源产品,Java 界中 Redis,Memcached,Cassandra,Hadoop,HBase,Lucene,spark,nginx,常见的⼤数据库底层,都使⽤了这个算法作为底层的存储算法。
介绍
MD5 ⽣成的哈希值是 128 ⽐特的。这⾥的哈希值指的是⼆进制的值,⽽不是 HEX 或 base64 格式化后的⼈类可读的值。通常我们提到的 32 位 MD5 是指由 32 个字符组成的,HEX 格式的 MD5。MurMurHash 算法家族的最新⼀员为MurMurHash3,⽀持32位和128位,推荐使⽤128位的MurMurHash3。是原作者被Google挖去之后基于Murmur2的缺陷做了改进。
32位的,在某些场景下,⽐如哈希的对象长度⼩于 128 位,或者存储空间要求占⽤⼩,或者需要把字符串转换成⼀个整数,这⼀特性就能帮上忙。当然,32 位哈希值发⽣碰撞的可能性就⽐ 128 位的要⾼得多。当数据量达到⼗万时,就很有可能发⽣碰撞。
贴⼀个⽹上的简单 MurMurHash2、MurMurHash3、MD5 的 benchmark:
这⾥的结论:MurMurHash3 128 位版本的速度是 MD5 的⼗倍。有趣的是,MurMurHash3 ⽣成 32 位哈希的⽤时⽐⽣成 128 位哈希的⽤时要长。原因在于MurMurHash3_128 针对现代 x64 平台cpu进⾏了优化。
Murmur是⼀个良好的通⽤散列函数系列,适⽤于⾮加密⽤法。MurmurHash提供以下好处:
简单(根据⽣成的汇编指令数量)。
良好的分布(⼏乎所有键组和铲⽃尺⼨均通过卡⽅检验。
好雪崩⾏为(最⼤偏差0.5%)。
良好的碰撞阻⼒(通过Bob Jenkin的frog.c酷刑测试。对于4字节键没有碰撞,没有⼩的(1到7位)差异)。
在Intel/AMD硬件上表现出⾊,散列质量和CPU消耗之间的良好折衷。
您当然可以使⽤它来散列UUID(就像任何其他⾼级散列函数⼀样:CityHash,Jenkins,Paul Hsieh等等)。现在,Redis bitset限制为4 GB位(512 MB)。因此,您需要将128位数据(UUID)减少到32位(散列值)。⽆论散列函数的质量如何,都会发⽣碰撞。
使⽤像Murmur这样的⼯程散列函数可以最⼤限度地提⾼分布质量,并最⼤限度地减少碰撞次数,但它不提供任何其他保证。
三、MurmurHash使⽤
1.导包
Java版:google guava 包中提供了使⽤⼯具类:
<groupId&le.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1.1-jre</version>
2.使⽤
import java.nio.charset.StandardCharsets;
lemon.hash.HashFunction;
lemon.hash.Hashing;
public class MurmurHashTest {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
String hexHashString = getHexHashString("qwerqwerqwer");
System.out.println(hexHashString);
}
}
public static String getHexHashString(String str) {
HashFunction hashFunction = Hashing.murmur3_128();
return hashFunction.hashString(str, StandardCharsets.UTF_8).toString();
}
}
四、性能测试
public class MurmurHashTest {
public static void main(String[] args) {
long l = System.nanoTime();
for (int i = 0; i < 10000 * 10000; i++) {
String hexHashString = getHexHashString("yzh123456qwer杨⼦");
// System.out.println(hexHashString);
}
long time = System.nanoTime() - l;
System.out.println("⼀亿数据,⼀共花费时间:" + time / (1000 * 1000 * 1000) + "秒");
long ns = time / (10000 * 10000);
System.out.println("⼀亿数据,每条数据花费时间:" + ns + "纳秒");
}
public static String getHexHashString(String str) {
HashFunction hashFunction = Hashing.murmur3_128();
return hashFunction.hashString(str, StandardCharsets.UTF_8).toString();
}
}
结果:
⼀亿数据,⼀共花费时间:20秒
⼀亿数据,每条数据花费时间:200纳秒
MD5的性能测试:菲律宾国旗
public class MurmurHashTest {
public static void main(String[] args) {
long l = System.nanoTime();
for (int i = 0; i < 10000 * 10000; i++) {
String hexHashString = getHexMD5String("yzh123456qwer杨⼦");
// System.out.println(hexHashString);
}
long time = System.nanoTime() - l;
System.out.println("⼀亿数据,⼀共花费时间:" + time / (1000 * 1000 * 1000) + "秒");
long ns = time / (10000 * 10000);
System.out.println("⼀亿数据,每条数据花费时间:" + ns + "纳秒");
}
public static String getHexMD5String(String str) {
return DigestUtils.Bytes());
}
}
MD5结果:
⼀亿数据,⼀共花费时间:32秒
⼀亿数据,每条数据花费时间:323纳秒
本⼈测试的字符串⽐较短,也可能是jar包不同版本以及使⽤的MacOS版本问题,虽然MurmurHash是⽐MD5快,但没有达到10倍的性能差距。
其它性能测试,含 hutool 包下的MurmurHash.hash64的使⽤:
;
import java.nio.charset.StandardCharsets;
import lang.MurmurHash;
lemon.hash.HashFunction;
建三江lemon.hash.Hashing;
import org.springframework.util.DigestUtils;
建成区public class MurmurHashTest {
public static void main(String[] args) {
String hexHashString = getHexHashStringWithGoogle128("user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTM L, like Gecko) Chrome/92.0.4515.107 Safari/537.36");
System.out.println("getHexHashStringWithGoogle128=" + hexHashString);
String hexHashString2 = getHexHashStringWithGoogle32("user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTM L, like Gecko) Chrome/92.0.4515.107 Safari/537.36");
System.out.println("getHexHashStringWithGoogle32=" + hexHashString2);
String hexHashString3 = getHexHashStringWithHutool64("user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML , like Gecko) Chrome/92.0.4515.107 Safari/537.36");
System.out.println("getHexHashStringWithHutool64=" + hexHashString3);
String hexHashString4 = getHexMD5String("user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36");
System.out.println("getHexMD5String=" + hexHashString4);
long l = System.nanoTime();
for (int i = 0; i < 10000 * 10000; i++) {
getHexHashStringWithGoogle128("user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrom e/92.0.4515.107 Safari/537.36");
}
long time = System.nanoTime() - l;
小哥白尼趣味科学System.out.println("⼀亿数据,getHexHashStringWithGoogle128⼀共花费时间:" + time / (1000 * 1000 * 1000) + "秒");
long l2 = System.nanoTime();
for (int i = 0; i < 10000 * 10000; i++) {
getHexHashStringWithGoogle32("user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/ 92.0.4515.107 Safari/537.36");
}
long time2 = System.nanoTime() - l2;
System.out.println("⼀亿数据,getHexHashStringWithGoogle32⼀共花费时间:" + time2 / (1000 * 1000 * 1000) + "秒");
long l3 = System.nanoTime();
for (int i = 0; i < 10000 * 10000; i++) {
getHexHashStringWithHutool64("user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/ 92.0.4515.107 Safari/537.36");
}
long time3 = System.nanoTime() - l3;
System.out.println("⼀亿数据,getHexHashStringWithHutool64⼀共花费时间:" + time3 / (1000 * 1000 * 1000) + "秒");
long l4 = System.nanoTime();
for (int i = 0; i < 10000 * 10000; i++) {
getHexMD5String("user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36");
}
long time4 = System.nanoTime() - l4;
System.out.println("⼀亿数据,getHexMD5String⼀共花费时间:" + time4 / (1000 * 1000 * 1000) + "秒");
}
public static String getHexHashStringWithGoogle128(String str) {
HashFunction hashFunction = Hashing.murmur3_128();
return hashFunction.hashString(str, StandardCharsets.UTF_8).toString();
}
public static String getHexHashStringWithGoogle32(String str) {
HashFunction hashFunction = Hashing.murmur3_32();
return hashFunction.hashString(str, StandardCharsets.UTF_8).toString();
}
public static String getHexHashStringWithHutool64(String data) {
long hash64 = MurmurHash.hash64(data);
HexString(hash64);
}
public static String getHexMD5String(String str) {
return DigestUtils.Bytes());
}
}
结果:
getHexHashStringWithGoogle128=3f3d5e5f32f9fff6a34dfa6329a83bf7
getHexHashStringWithGoogle32=2cb92c51
getHexHashStringWithHutool64=4742386bfc5110a8
yy公司
getHexMD5String=05fbb1053d692f9f6730d1a24e577a92
⼀亿数据,getHexHashStringWithGoogle128⼀共花费时间:36秒
⼀亿数据,getHexHashStringWithGoogle32⼀共花费时间:19秒
⼀亿数据,getHexHashStringWithHutool64⼀共花费时间:18秒
⼀亿数据,getHexMD5String⼀共花费时间:62秒

本文发布于:2024-09-21 00:28:48,感谢您对本站的认可!

本文链接:https://www.17tex.com/xueshu/398441.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:算法   散列   数据   函数   碰撞   加密
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2024 Comsenz Inc.Powered by © 易纺专利技术学习网 豫ICP备2022007602号 豫公网安备41160202000603 站长QQ:729038198 关于我们 投诉建议