`

MurmurHash一致性Hash算法JAVA版

阅读更多

一.背景介绍

MurmurHash算法:高运算性能,低碰撞率,由Austin Appleby创建于2008年,现已应用到Hadoop、libstdc++、nginx、libmemcached等开源系统。2011年Appleby被Google雇佣,随后Google推出其变种的CityHash算法。官方只提供了C语言的实现版本。 

Java界中Redis,Memcached,Cassandra,HBase,Lucene都用它。

在Java的实现,Guava的Hashing类里有,上面提到的Jedis,Cassandra里都有Util类。

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

 

一.实现类

 

import java.math.BigDecimal;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * 一致性Hash的一种算法 高效低碰撞率
 */
public class Murmurs {

    /**
     * murmur hash算法实现
     */
    public static Long hash(byte[] key) {

        ByteBuffer buf = ByteBuffer.wrap(key);
        int seed = 0x1234ABCD;

        ByteOrder byteOrder = buf.order();
        buf.order(ByteOrder.LITTLE_ENDIAN);

        long m = 0xc6a4a7935bd1e995L;
        int r = 47;

        long h = seed ^ (buf.remaining() * m);

        long k;
        while (buf.remaining() >= 8) {
            k = buf.getLong();

            k *= m;
            k ^= k >>> r;
            k *= m;

            h ^= k;
            h *= m;
        }

        if (buf.remaining() > 0) {
            ByteBuffer finish = ByteBuffer.allocate(8).order(
                    ByteOrder.LITTLE_ENDIAN);
            // for big-endian version, do this first:
            // finish.position(8-buf.remaining());
            finish.put(buf).rewind();
            h ^= finish.getLong();
            h *= m;
        }

        h ^= h >>> r;
        h *= m;
        h ^= h >>> r;

        buf.order(byteOrder);
        return h;
    }

    public static Long hash(String key) {
        return hash(key.getBytes());
    }



    /**
     * Long转换成无符号长整型(C中数据类型)
     */
    public static BigDecimal readUnsignedLong(long value) {
        if (value >= 0)
            return new BigDecimal(value);
        long lowValue = value & 0x7fffffffffffffffL;
        return BigDecimal.valueOf(lowValue).add(BigDecimal.valueOf(Long.MAX_VALUE)).add(BigDecimal.valueOf(1));
    }

    /**
     * 返回无符号murmur hash值
     */
    public static BigDecimal hashUnsigned(String key) {
        return readUnsignedLong(hash(key));
    }
    public static BigDecimal hashUnsigned(byte[] key) {
        return readUnsignedLong(hash(key));
    }
}

 

 

二.测试类

import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

import static org.assertj.core.api.Assertions.assertThat;

public class MurmurHashTest {

    private static final Logger logger = LoggerFactory.getLogger(MurmurHashTest.class);

    @Test
    public void test() throws IOException {
        assertThat(Murmurs.hashUnsigned("chenshuo").toString()).isEqualTo("5016608279269930526");
        assertThat(Murmurs.hashUnsigned("shaoguoqing").toString()).isEqualTo("17121371936686143062");
        assertThat(Murmurs.hashUnsigned("baozenghui").toString()).isEqualTo("5451996895512824982");
        assertThat(Murmurs.hashUnsigned("05ff62ff6f7749ffff43ffff6673ff65").toString()).isEqualTo("10652549470333968609");
        assertThat(Murmurs.hashUnsigned("hahahaha").toString()).isEqualTo("15134676900169534748");
        assertThat(Murmurs.hashUnsigned("hahah1369531321aha5466sfdfaerttedddd56da").toString()).isEqualTo("6439159232526071817");
        assertThat(Murmurs.hashUnsigned("测试汉字").toString()).isEqualTo("1146745369200541601");
        assertThat(Murmurs.hashUnsigned("1234566大大21".getBytes("GBK")).toString()).isEqualTo("10129762727109086067");
        assertThat(Murmurs.hashUnsigned("12345665哦4哦3我的妈呀21".getBytes("GBK")).toString()).isEqualTo("5141842319936259217");
    }

}

 

 

 

 

1
0
分享到:
评论
1 楼 windlike 2015-07-28  

相关推荐

    murmurhash

    这对于分布式系统尤其重要,因为它可以保证不同节点之间的一致性。 5. **源码开放**:MurmurHash的源代码是开源的,这使得开发者可以自由地查看、使用和改进算法。在压缩包中的`murmurhash.c`文件就是MurmurHash的...

    MurMurHash3:MurMurHash3算法的纯C#实现

    - **兼容性**: 考虑与其他语言或库的 MurMurHash3 实现保持一致,以确保跨平台的一致性。 - **错误处理**: 实现应处理无效的输入,如空字符串、负长度等,并提供清晰的错误信息。 在 `MurMurHash3-master` 压缩包中...

    前端项目-murmurhash3js.zip

    9. **测试**:为了确保哈希函数的正确性和一致性,项目可能包含了单元测试,使用了如Jest、Mocha等测试框架。 10. **应用场景**:MurmurHash3在前端项目中可能用于生成唯一ID、数据索引、缓存键、指纹识别等场景。 ...

    ConsistentHash:一致性hash算法的 java 和 C++ 实现

    一致性哈希(Consistent Hashing)是一种分布式哈希表(DHT, Distributed Hash Table)算法,主要用于解决在分布式系统中数据存储和检索的问题,尤其是在动态扩展集群节点时,能够尽可能地减少缓存重建,保持系统...

    Mycat一致性哈希分片算法1

    在Mycat的一致性哈希分片算法中,murmur算法是一个核心组件。murmur算法是一个非加密哈希函数,具有高速运算和良好的分布性。Mycat使用murmur算法将数据的哈希值映射到虚拟节点上,然后根据虚拟节点的映射关系将数据...

    murmurhash:Mur MurmurHash2的Cython绑定

    它提供了Python接口来调用MurmurHash2算法,使得Python开发者无需直接处理C++代码,也能利用MurmurHash2的高效性。Cymur通常包括以下功能: 1. **哈希函数接口**:提供一个简单的函数调用,如`murmurhash2(key, ...

    python3-mmhash:MurmurHash2 的 Python3 端口

    Python3-mmhash是一个开源项目,它是MurmurHash2算法的Python3实现。MurmurHash2是一个非加密哈希函数,由Austin Appleby在2008年设计,广泛用于数据索引、数据去重和快速查找等场景。它的特点是速度快、散列冲突的...

    Murmur3 hash in C.zip

    3. **末尾处理**:对于最后一块不足完整块的数据,进行特殊处理以确保一致性。 4. **结束**:最后将计算得到的哈希值进行一次XOR操作,以提高分布均匀性。 以下是一个简化的C语言实现框架: ```c #include #...

    Go-AnchorHash:是Go的最小内存AnchorHash一致哈希实现

    相比于传统的Jenkins Hash或MurmurHash,AnchorHash可能更侧重于在特定场景下优化内存效率,尤其是在资源受限的环境中。 **3. Go-AnchorHash特点** - **内存效率高**:Go-AnchorHash 的设计重点在于降低内存使用,...

    murmur:非加密哈希Murmur3的实现

    其中,MurmurHash系列算法以其高效、低冲突的特性脱颖而出,而Murmur3作为该系列的最新版本,更是备受瞩目。本文将深入探讨Murmur3非加密哈希算法的原理及其在Elixir语言中的具体实现。 Murmur3算法的设计目标是...

    scala哈希:Scala的快速非加密哈希函数

    在Scala中,哈希函数扮演着重要的角色,特别是在数据处理、键值存储和一致性哈希等场景。本篇文章将深入探讨Scala中的哈希函数,尤其是快速非加密哈希函数,如MurmurHash3和XXHash。 哈希函数是将任意大小的数据...

    Cassandra-架构讲解

    Gossip协议的使用允许Cassandra在面对故障恢复和扩展节点时,能快速达成全网络内的一致性状态。 Token(令牌)在Cassandra中用于确定数据应该存储到哪个节点上。Cassandra使用Murmur3Hash算法来计算行键(Row key)...

    Go-ContentDefinedChunking(CDC)中Go中的实现

    3. **哈希计算**:使用Go的`hash`包,例如`hash/crc32`或`hash/murmur3`,计算窗口内的数据哈希。 4. **分块判断**:比较连续数据段的哈希值,当超过预设阈值(比如两个哈希值不同时)时,生成新块。 5. **块编码与...

    wyhll:基于2位HyperLogLog的梦想精确近似集基数估计器。 比Redis HyperLogLog更准确,更快

    2. **哈希函数的选择**:为了确保输入元素的哈希值均匀分布,wyhll可能会选择强一致性且速度快的哈希函数,如MurmurHash或CityHash。 3. **最大零位前缀的计算**:代码会使用位操作来快速查找最长的连续零位,这是...

    在C#中有效地使用列表作为字典键

    更优化的策略可能是将元素的哈希值按某种顺序组合起来,如使用FNV-1a哈希算法或者MurmurHash等高效哈希函数。 其次,考虑到列表的可变性,使用列表作为字典键需要谨慎。一旦列表被用作键并添加到字典中,修改该列表...

Global site tag (gtag.js) - Google Analytics