一致性hash算法的实现,hash算法和hash一致性

  一致性hash算法的实现,hash算法和hash一致性

  一、哈希函数1.1定义哈希函数(英文:Hash function),也称为哈希算法和哈希函数,是一种从任何种类的数据中创建小型数字“指纹”的方法。哈希函数将一条消息或数据压缩成摘要,使得数据量变小,数据格式固定。该函数对数据进行加扰和混合,并重新创建一个称为哈希值(哈希代码)的指纹。哈希值通常由一串短的随机字母和数字表示。一个好的散列函数在输入字段中很少出现散列冲突。

  1.2特性加密:加密存储在数据库中的密码字符串。因为哈希算法计算出来的哈希值是不可逆的(无法计算回原来的值),所以可以有效的保护密码。

  压缩:通过哈希算法将任意长度的输入转换成固定长度的输出。

  应用:数据保护,确保真实信息的传输,哈希表,纠错,语音识别,信息安全。

  1.3常见的哈希算法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

  这里记录一下murHash,二代几乎称霸江湖。

  二。murmurhashMurmurHash算法:高计算性能,低碰撞率。它是由奥斯汀艾波在2008年创立的,已经被应用于Hadoop、libstdc、nginx和libmemcached等开源系统。艾波于2011年被谷歌聘用,随后谷歌推出了其变体CityHash算法。官方只提供了C语言的实现版本。

  MurmurHash是一个不加密的哈希函数,适用于一般的哈希检索操作。与其他流行的哈希函数相比,murHash的随机分布特性对于规律性强的密钥更好。

  2.1特点1。很快。

  Murhash 3比MD5快。

  2.低碰撞。

  128位版本的murhash 3有一个128位的哈希值,就像MD5一样。18位哈希值,在只有几千万数据的情况下,基本不用担心碰撞。

  3.高度混乱。

  哈希值是“偶数”,如果用于哈希表、布隆过滤器等。元素会均匀分布。2.2 MD5生成的哈希值为128位。这里的哈希值指的是二进制值,而不是十六进制或base64格式的人类可读值。通常所说的32位MD5是指由32个字符组成的十六进制格式的MD5。MurMurHash算法家族最新成员是MurMurHash3,支持32位和128位,推荐128位MurMurHash3。是原作者被谷歌挖了出来,基于Murmur2的缺陷进行了改进。

  32位,在某些场景下,比如哈希对象的长度小于128位,或者存储空间较小,或者需要将字符串转换成整数。这个特性会有所帮助。当然,32位哈希之间发生冲突的可能性要比128位哈希高得多。当数据量达到10万时,发生碰撞的概率很大。

  在网上贴一个简单的MurHash2,MurHash3,MD5的基准测试:

  https://github . com/space wander/Lua-resty-murmurhash 3/blob/master/readme . MD # when-should-I-use-it

  这里的结论:MurMurHash3 128位版本比MD5快十倍。有趣的是,MurMurHash3生成32位Hash比生成128位hash需要更长的时间。原因是MurHash3_128是针对现代x64平台cpu优化的。

  Mur是一个很好的通用哈希函数系列,适合不加密使用。MurmurHash提供了以下好处:

  简单(根据生成的汇编指令数)。

  好的分布(几乎所有的关键组和桶大小都通过了卡方检验。

  良好的雪崩行为(最大偏差0.5%)。

  抗碰撞性好(通过Bob Jenkin的frog.c酷刑测试。对于4字节的密钥,没有碰撞,没有小(1到7位)的差别)。

  在Intel/AMD硬件上的出色性能,哈希质量和CPU消耗之间的良好折衷。

  您当然可以使用它来散列UUID(就像任何其他高级散列函数一样:CityHash,Jenkins,Paul Hsieh等等)。现在,Redis位集限制为4 GB位(512兆字节).因此,您需要将128位数据(UUID)减少到32位(散列值)。无论散列函数的质量如何,都会发生碰撞。

  使用像低语这样的工程散列函数可以最大限度地提高分布质量,并最大限度地减少碰撞次数,但它不提供任何其他保证。

  2.3 应用

  广泛应用于各开源产品,Java界中Redis,Memcached,Cassandra,Hadoop,HBase,Lucene,spark,nginx,常见的大数据库底层,都使用了这个算法作为底层的存储算法。

  在爪哇的实现,番石榴的散列法类里有,上面提到的卡桑德拉杰迪斯里都有跑龙套类。

  但存在的问题是由于爪哇的数据类型长的与C语言中无符号长整型uint64_t有区别,导致爪哇输出版本存在负数,针对这个问题进行了修改;另外需要注意的是中文不同编码(UTF-8或GBK)会导致输出结果的不同,使用中需要统一编码。

  三、Java编码实现

  导入Java。nio。字节缓冲区;

  导入Java。nio。字节顺序;

  /**

  @作者:黄艺博

  @日期:2022/7/18 17:42

  @描述:MurMurHash一致性混杂的一种算法高效低碰撞率

  */

  公共类MurHashUtil {

  /**

  * MurMurHash算法,性能高,碰撞率低

  * @param密钥字节[]

  * @返回长的

  公共静态长哈希(byte[] key) {

  字节缓冲区。wrap(键);

  int seed=0x1234ABCD

  字节顺序字节顺序=buf。order();

  buf.order(ByteOrder .LITTLE _ ENDIAN);

  长m=0 xc6a 4a 7935 bd1e 995 l;

  int r=47

  长h=种子^(buf。剩余()* m);

  长k;

  while (buf.remaining()=8) {

  k=buf。getlong();

  k *=m;

  ^=k

  k *=m;

  ^=k;

  h *=m;

  if (buf.remaining() 0) {

  字节缓冲结束=字节缓冲。分配(8).订单(

  字节序.LITTLE _ ENDIAN);

  //对于大端版本,首先执行以下操作:

  //完成。位置(8个缓冲器。剩余());

  finish.put(buf).rewind();

  ^=完成。getlong();

  h *=m;

  ^=h

  h *=m;

  ^=h

  buf。顺序(字节顺序);

  返回h;

  * 计算混杂值

  * @param密钥字符串

  * @返回长的

  公共静态长哈希(字符串密钥){

  返回哈希(键。getbytes());

  *长转换成无符号长整型(三)中数据类型)

  * Java的数据类型长的与C语言中无符号长整型uint64_t有区别,导致爪哇输出版本存在负数

  * @param值

  * @返回

  public static Long readUnsignedLong(Long value){

  如果(值=0){

  返回值;

  返回值0x7fffffffffffffffL

  * 返回无符号杂音散列值

  * @param key

  * @返回

  公共静态长哈希签名(字符串密钥){

  返回readUnsignedLong(hash(key));

  * 返回无符号杂音散列值

  * @param key

  * @返回

  public static Long hashUnsigned(byte[]key){

  返回readUnsignedLong(hash(key));

  }

  }

  * 测试

  公共静态void main(String[] args) {

  list String list=new ArrayList();

  list.add(重庆

  list.add(长沙

  list.add(广州

  list.add(深圳

  列表。地址(001 C4 becd 89 f 49 f 7 B1 c 52 Fe 4 fcd 54397

  列表。添加(002 b 320 c0e 0347 A8 bcea 7663192d 8303

  列表。地址0035420515 a 24d 9d 875 E6 c 4399 bec 8 e 3

  列表。地址(00701 f4c 12364 bedb 626 DD 136 CBC 998 b

  列表。地址(008d 028903 da 483 fbee8d 721 b2e 73934

  列表。地址(00b 9 DC E4 EC 2747 c 0 AEA 6 EB 0494 e 38717)

  对于(字符串城市:列表){

  长哈希=哈希签名(城市);

  系统。出去。println(哈希);

  System.out.println(哈希% 10);

  }

  }

  ## 四番石榴碎类

  爪哇版:谷歌番石榴包中提供了使用工具类

  * 引入谷歌番石榴依赖

  属国

  groupId com。谷歌。番石榴/groupId

  番石榴/artifactId

  版本31.1-JRE/版本

  /依赖关系

  ` ` java

  导入com。谷歌。常见。哈希。哈希函数;

  导入com。谷歌。常见。哈希。哈希;

  导入Java。nio。字符集。标准字符集;

  * @作者:黄艺博

  * @日期:2022/7/18 17:34

  * @描述:MurMurHash一致性混杂的一种算法高效低碰撞率

  公共类MurHashUtils {

  * MurMurHash算法,性能高,碰撞率低

  * @param字符串

  * @返回长的

  公共静态长哈希(字符串str) {

  哈希函数哈希函数=哈希。mur mur 3 _ 128();

  返回hashFunction.hashString(str,StandardCharsets .UTF_8).asLong();

  *长转换成无符号长整型(三)中数据类型)

  * Java的数据类型长的与C语言中无符号长整型uint64_t有区别,导致爪哇输出版本存在负数

  * @param值长

  * @返回长的

  public static Long readUnsignedLong(Long value){

  如果(值=0){

  返回值;

  返回值长整型最大值

  * 返回无符号杂音散列值

  * @param key

  * @返回

  公共静态长哈希签名(字符串密钥){

  返回readUnsignedLong(hash(key));

  }

  列表。add( 001 C4 becd 89 f 49 f 7 B1 c 52 Fe 4 fcd 54397 );

  列表。add( 002 b 320 c0e 0347 A8 bcea 7663192d 8303 );

  列表。add( 0035420515 a 24d 9d 875 E6 c 4399 bec 8 e 3 );

  列表。add( 00701 f4c 12364 bedb 626 DD 136 CBC 998 b );

  列表。add( 008d 028903 da 483 fbee8d 721 b2e 73934 );

  列表。add( 00 b 9 DC E4 EC 2747 c 0 AEA 6 EB 0494 e 38717 );

  对于(字符串城市:列表){

  长哈希=哈希签名(城市);

  系统。出去。println(哈希);

  System.out.println(哈希% 10);

  }

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: