一、哈希函数
散列函数(英语: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的随机分布特征表现更良好。
MurMurHash3 比 MD5 快。
2.低碰撞。
MurMurHash3 128 位版本哈希值是 128 位的,跟 MD5 一样。128 位的哈希值,在数据量只有千万级别的情况下,基本不用担心碰撞。
3.高混淆。
散列值比较“均匀”,如果用于哈希表,布隆过滤器等, 元素就会均匀分布。
广泛应用于各开源产品,Java 界中 Redis,Memcached,Cassandra,Hadoop,HBase,Lucene,spark,nginx,常见的大数据库底层,都使用了这个算法作为底层的存储算法。
MD5 生成的哈希值是 128 bit。这里的哈希值指的是二进制的值,而不是 HEX 或 base64 格式化后的人类可读的值。通常我们提到的 32 位 MD5 是指由 32 个字符组成的,HEX 格式的 MD5。MurMurHash 算法家族的最新一员为MurMurHash3,支持32位和128位,推荐使用128位的MurMurHash3。是原作者被Google挖去之后基于Murmur2的缺陷做了改进。
32位的,在某些场景下,比如哈希的对象长度小于 128 位,或者存储空间要求占用小,或者需要把字符串转换成一个整数,这一特性就能帮上忙。当然,32 位哈希值发生碰撞的可能性就比 128 位的要高得多。当数据量达到十万时,就很有可能发生碰撞。
Murmur是一个良好的通用散列函数系列,适用于非加密用法。MurmurHash提供以下好处:
简单(根据生成的汇编指令数量)。
良好的分布(几乎所有键组和铲斗尺寸均通过卡方检验。
好 雪崩 行为(最大偏差0.5%)。
良好的碰撞阻力(通过Bob Jenkin的frog.c酷刑测试。对于4字节键没有碰撞,没有小的(1到7位)差异)。
在Intel/AMD硬件上表现出色,散列质量和CPU消耗之间的良好折衷。
您当然可以使用它来散列UUID(就像任何其他高级散列函数一样:CityHash,Jenkins,Paul Hsieh等等)。使用像Murmur这样的工程散列函数可以最大限度地提高分布质量,并最大限度地减少碰撞次数,但它不提供任何其他保证。
三、MurmurHash使用
Java版:google guava 包中提供了使用工具类:
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>30.1.1-jre</version>
</dependency>
import java.nio.charset.StandardCharsets;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
* @author yangzihe
* @date 2021/8/14
public class MurmurHashTest {
public static void main(String[] args) {
for (int i = 0; i < 100; i++) {
String hexHashString = getHexHashString("yzh123456qwer杨子");
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.md5DigestAsHex(str.getBytes());
MD5结果:
一亿数据,一共花费时间:32秒
一亿数据,每条数据花费时间:323纳秒
本人测试的字符串比较短,也可能是jar包不同版本以及使用的MacOS版本问题,虽然MurmurHash是比MD5快,但没有达到10倍的性能差距。
其它性能测试,含 hutool 包下的MurmurHash.hash64的使用:
package com.yy.armor.engine.core;
import java.nio.charset.StandardCharsets;
import cn.hutool.core.lang.MurmurHash;
import com.google.common.hash.HashFunction;
import com.google.common.hash.Hashing;
import org.springframework.util.DigestUtils;
* @author yangzihe
* @date 2021/8/14
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 (KHTML, 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 (KHTML, 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) Chrome/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);
return Long.toHexString(hash64);
public static String getHexMD5String(String str) {
return DigestUtils.md5DigestAsHex(str.getBytes());
getHexHashStringWithGoogle128=3f3d5e5f32f9fff6a34dfa6329a83bf7
getHexHashStringWithGoogle32=2cb92c51
getHexHashStringWithHutool64=4742386bfc5110a8
getHexMD5String=05fbb1053d692f9f6730d1a24e577a92
一亿数据,getHexHashStringWithGoogle128一共花费时间:36秒
一亿数据,getHexHashStringWithGoogle32一共花费时间:19秒
一亿数据,getHexHashStringWithHutool64一共花费时间:18秒
一亿数据,getHexMD5String一共花费时间:62秒
再贴一个网上简单的 MurMurHash2、MurMurHash3、MD5 的 benchmark:
lua-resty-murmurhash3/README.md at master · spacewander/lua-resty-murmurhash3 · GitHub
这里的结论:MurMurHash3 128 位版本的速度是 MD5 的十倍。
mmh3安装方法
哈希方法主要有MD、SHA、
Murmur、City
Hash、MAC等几种方法。mmh3全程
murmurhash3,是一种非加密的
哈希算法,常用于hadoop等分布式存储情境中,在anaconda中安装使用命令
pip install mmh3
报错如下:
Microsoft Visual C++ 14.0 is required
显示缺少C++ 14的库文件,选择登录网站 https://visualstudio.microsoft.com/downloads/
下载Visual Studio2015,自动安装后运行
pip install mmh3
加密哈希和非加密哈希-MM是非加密哈希
首先了解下加密哈希和非加密哈希,
加密哈希函数旨在保证安全性,很难找到碰撞。即:给定的散列h很难找到的消息m;很难找到产生相同的哈希值的消息m1和m2。
非加密哈希函数只是试图避免非恶意输入的冲突。作为较弱担保的交换,它们通常更快。如果数据量小,或者不太在意哈希碰撞的频率,甚至可以选择生成哈希值小的哈希算法,占用更小的空间。
Smhasher-评价哈希算法的...
文章目录MurmurHashMurmurHash通过了【卡方检验】和【雪崩测试】什么是卡方检验?什么是雪崩测试?各类Hash算法碰撞概率MurmurHash3 在Scala的使用
本文内容收集于互联网。
MurmurHash 是一种 非加密 函数的哈希函数。
*MurmurHash3_最详细的介绍
MurmurHash3原理讲解
MurmurHash
MurmurHash 是一种经过广泛测试且速度很快的非加密哈希函数。它有Austin Appleby于2008年创建,并存在多种变体,名字来自
由于项目中有报文排重需求,所以会将报文字符串作为分布式锁key。考虑到报文不定长并且散列性不太好,如其作为锁key,特别是当key值过大时,使用redis进行读写都会有相对的性能下降。
参考文献里测试对比:
长度为10:写平均耗时0.053ms,读0.040ms
长度为20000:写平均耗时0.352ms,读0.084ms
一种简单的方案是对报文进...
Murmur哈希是一种非加密函数的哈希函数,下面我们在介绍哈希函数之前我们需要了解一下什么是好的哈希函数。
1.好的哈希函数应该卡方测试(chi-squared test)
卡方测试:
Xc2=∑i=0N−1(Oi−Ei)2/Ei,其中Oi为观察量,而Ei为估计量{X_c^2 = \sum_ {i=0}^{N-1}(O_i-E_i)^2/E_i},其中O_i为观察量,而E_i为估计量Xc2=∑i=0N−1(Oi−Ei)2/Ei,其中Oi为观察量,而Ei为估计量
我们测试的方案就是给出大量的数据
1.数据库中索引概念
在关系数据库中,索引是一种单独的、物理的对数据库表中一列或多列的值进行排序的一种存储结构,它是某个表中一列或若干列值的集合和相应的指向表中物理标识这些值的数据页的逻辑指针清单。索引的作用相当于图书的目录,可以根据目录中的页码快速找到所需的内容。
2.索引优点和缺点
索引可以避免全表扫描,加快查询速度。多数查询可以仅扫描少量索引页及数据页,而不是遍历所有...
什么是hash算法:
一般翻译做“散列”,也有直接音译为“哈希”的,就是把任意长度的输入(又叫做预映射, pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值。
hash算法有几个特点:
1、只能通过原文计算出hash值,而且每次计算都一样,不能通过hash值计算原文。
2、原文的微小变化就能是hash值发生巨大变化。
3、一个好的hash算法还能尽量避免发生hash值重复的情况,也叫hash碰撞。
hash的用途:
1、密码的保存:
实际的工程当中我们一般不存储明文密