溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

基于murmurhash+List實(shí)現(xiàn)一致性Hash

發(fā)布時(shí)間:2020-07-13 11:42:04 來源:網(wǎng)絡(luò) 閱讀:589 作者:shayang88 欄目:編程語言

一致性Hash原理這里不再介紹了,下面是一個(gè)簡單版的實(shí)現(xiàn)方案。

1、MurmurHashUtils

package com.jane.pos.sync.utils;

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

/**
 * 利用murmurHash實(shí)現(xiàn)高性能的低碰撞的純數(shù)字hash值
 */
public class MurmurHashUtils {

    private static final String UTF_8 = "UTF-8";

    public static long hash74A(byte[] data, int seed) {
        return hash74A(ByteBuffer.wrap(data), seed);
    }

    public static long hash74A(ByteBuffer buf, int seed) {
        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(byte[] key) {
        return hash74A(key, 0x1234ABCD);
    }

    public static long hash(String key) {
        return hash(encode(key));
    }

    /**
     * Long轉(zhuǎn)換成無符號(hào)長整型(C中數(shù)據(jù)類型)
     */
    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));
    }

    /**
     * 返回?zé)o符號(hào)murmur hash值
     */
    public static BigDecimal hashUnsigned(String key) {
        return readUnsignedLong(hash(key));
    }

    public static BigDecimal hashUnsigned(byte[] key) {
        return readUnsignedLong(hash(key));
    }

    private static byte[] encode(String data) {
        try {
            return data.getBytes(UTF_8);
        } catch (UnsupportedEncodingException e) {
            throw new IllegalArgumentException(e);
        }
    }
}

2、HashUtils

package com.jane.pos.sync.utils;

import java.math.BigDecimal;
import java.util.*;

public class HashUtils {

    /**
     * 真實(shí)節(jié)點(diǎn)虛擬化,為了節(jié)點(diǎn)分布均衡
     * @param realNodes 真實(shí)節(jié)點(diǎn)列表
     * @param inventedNum 每個(gè)節(jié)點(diǎn)虛擬的節(jié)點(diǎn)個(gè)數(shù)
     * @param hashList 用數(shù)組模擬hash環(huán)
     * @return
     */
    public static Map<BigDecimal, String> inventedNodes(String[] realNodes, int inventedNum, List<BigDecimal> hashList) {
        //虛擬點(diǎn)和真實(shí)節(jié)點(diǎn)的對(duì)應(yīng)關(guān)系
        Map<BigDecimal, String> map = new HashMap<>();
        if(realNodes.length > 0) {
            for (String node : realNodes) {
                for(int i = 1; i <= inventedNum; i++) {
                    BigDecimal hashCode = MurmurHashUtils.hashUnsigned(node + i);
                    map.put(hashCode, node);
                    //組建hash值數(shù)組,模擬hash環(huán)
                    hashList.add(hashCode);
                }
            }
        }

        return map;
    }

    /**
     * 根據(jù)key獲取固定的一致性節(jié)點(diǎn)
     * @param realNodes 真實(shí)節(jié)點(diǎn)
     * @param inventedNum 虛擬的節(jié)點(diǎn)數(shù)量
     * @param key hash的key,這個(gè)key對(duì)應(yīng)一個(gè)固定的唯一的真實(shí)節(jié)點(diǎn)
     * @return
     */
    public static String getFixedOnlyNode(String[] realNodes, int inventedNum, String key) {
        List<BigDecimal> hashList = new ArrayList<>();
        Map<BigDecimal, String> map = inventedNodes(realNodes, inventedNum, hashList);
        //hash數(shù)組排序
        Collections.sort(hashList);
        BigDecimal findHash = MurmurHashUtils.hashUnsigned(key);
        for(BigDecimal item : hashList){
            //第一個(gè)大的節(jié)點(diǎn),即為要的節(jié)點(diǎn)
            if(item.compareTo(findHash) == 1 ) {
                return map.get(item);
            }
        }
        //未命中的key,對(duì)節(jié)點(diǎn)取余當(dāng)作下標(biāo),獲取真實(shí)節(jié)點(diǎn)
        return map.get(findHash.divideAndRemainder(BigDecimal.valueOf(hashList.size()))[1]);
    }

}

3、啟動(dòng)文件

public static void main(String[] args) throws InterruptedException {

        String storeNo = "store";
        String[] nodes = {"tag01","tag02","tag03","tag04","tag05"};
        for (int i = 0; i <= 10; i++){
            String key = storeNo + i;
            for (int j = 0; j <= 10; j++) {
                String node = HashUtils.getFixedOnlyNode(nodes, 10, key);
                System.out.println(key + "----" + node);
            }
        }
    }

4、結(jié)果

store0----tag01
store0----tag01
store0----tag01
store0----tag01
store0----tag01
store0----tag01
store0----tag01
store0----tag01
store0----tag01
store0----tag01
store0----tag01
store1----tag03
store1----tag03
store1----tag03
store1----tag03
store1----tag03
store1----tag03
store1----tag03
store1----tag03
store1----tag03
store1----tag03
store1----tag03
store2----tag01
store2----tag01
store2----tag01
store2----tag01
store2----tag01
store2----tag01
store2----tag01
store2----tag01
store2----tag01
store2----tag01
store2----tag01
store3----tag01
store3----tag01
store3----tag01
store3----tag01
store3----tag01
store3----tag01
store3----tag01
store3----tag01
store3----tag01
store3----tag01
store3----tag01
store4----tag02
store4----tag02
store4----tag02
store4----tag02
store4----tag02
store4----tag02
store4----tag02
store4----tag02
store4----tag02
store4----tag02
store4----tag02
store5----tag05
store5----tag05
store5----tag05
store5----tag05
store5----tag05
store5----tag05
store5----tag05
store5----tag05
store5----tag05
store5----tag05
store5----tag05
store6----tag01
store6----tag01
store6----tag01
store6----tag01
store6----tag01
store6----tag01
store6----tag01
store6----tag01
store6----tag01
store6----tag01
store6----tag01
store7----tag05
store7----tag05
store7----tag05
store7----tag05
store7----tag05
store7----tag05
store7----tag05
store7----tag05
store7----tag05
store7----tag05
store7----tag05
store8----tag05
store8----tag05
store8----tag05
store8----tag05
store8----tag05
store8----tag05
store8----tag05
store8----tag05
store8----tag05
store8----tag05
store8----tag05
store9----tag02
store9----tag02
store9----tag02
store9----tag02
store9----tag02
store9----tag02
store9----tag02
store9----tag02
store9----tag02
store9----tag02
store9----tag02
store10----tag03
store10----tag03
store10----tag03
store10----tag03
store10----tag03
store10----tag03
store10----tag03
store10----tag03
store10----tag03
store10----tag03
store10----tag03
向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請(qǐng)聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI