freebsd分片重组算法_mongodb分片算法

freebsd分片重组算法_mongodb分片算法Q:你们redis怎么做的分布式A:我们公司redis用的murmurHash做的分片;Q:讲讲murmurHash的原理呗A:额……这块没有深入了解过(真TM掉分)哈希算法简单来说就是将一个元素映射成另一个元素,可以简单分类两类,加密哈希,如MD5,SHA256等,非加密哈希,如MurMurHash,CRC32,DJB等。这里说说Jedis中的Shard是如何使用一致性hash的首先是hash函数,在Jedis中有两种Hash算法可供选择,分别是MurMurHash和MD5.按照.

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

Q:你们redis怎么做的分布式
A:我们公司redis用的murmurHash做的分片;
Q:讲讲murmurHash的原理呗
A:额……这块没有深入了解过(真TM掉分)

哈希算法简单来说就是将一个元素映射成另一个元素,可以简单分类两类,

  1. 加密哈希,如MD5,SHA256等,
  2. 非加密哈希,如MurMurHash,CRC32,DJB等。

这里说说Jedis中的Shard是如何使用一致性hash的

首先是hash函数,在Jedis中有两种Hash算法可供选择,分别是MurMurHashMD5. 按照Jedis的说法MurmurHash更快,效果更好些。

package redis.clients.util;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public interface Hashing { 
   
    public static final Hashing MURMUR_HASH = new MurmurHash();
    public ThreadLocal<MessageDigest> md5Holder = new ThreadLocal<MessageDigest>();

    public static final Hashing MD5 = new Hashing() { 
   
	public long hash(String key) { 
   
	    return hash(SafeEncoder.encode(key));
	}

	public long hash(byte[] key) { 
   
	    try { 
   
		if (md5Holder.get() == null) { 
   
		    md5Holder.set(MessageDigest.getInstance("MD5"));
		}
	    } catch (NoSuchAlgorithmException e) { 
   
		throw new IllegalStateException("++++ no md5 algorythm found");
	    }
	    MessageDigest md5 = md5Holder.get();

	    md5.reset();
	    md5.update(key);
	    byte[] bKey = md5.digest();
	    long res = ((long) (bKey[3] & 0xFF) << 24)
		    | ((long) (bKey[2] & 0xFF) << 16)
		    | ((long) (bKey[1] & 0xFF) << 8) | (long) (bKey[0] & 0xFF);
	    return res;
	}
    };

    public long hash(String key);

    public long hash(byte[] key);
}

来看一下jedis-2.4.2的MurmurHash

涉及一些nio的buffer操作,这里不说了

package redis.clients.util;

import com.google.common.hash.Hashing;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;


public class MurmurHash implements Hashing { 
   

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

    public static int hash(byte[] data, int offset, int length, int seed) { 
   
        return hash(ByteBuffer.wrap(data, offset, length), seed);
    }

    public static int hash(ByteBuffer buf, int seed) { 
   
        // save byte order for later restoration
        ByteOrder byteOrder = buf.order();
        buf.order(ByteOrder.LITTLE_ENDIAN);

        int m = 0x5bd1e995;
        int r = 24;

        int h = seed ^ buf.remaining();

        int k;
        while (buf.remaining() >= 4) { 
   
            k = buf.getInt();

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

            h *= m;
            h ^= k;
        }

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

        h ^= h >>> 13;
        h *= m;
        h ^= h >>> 15;

        buf.order(byteOrder);
        return h;
    }

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

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

    public static long hash64A(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 long hash(byte[] key) { 
   
        return hash64A(key, 0x1234ABCD);
    }

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

我们公司自己做的封装就不贴code了,
看一下Jedis自己的一致性Hash

public S getShardInfo(byte[] key) { 
   
	SortedMap<Long, S> tail = nodes.tailMap(algo.hash(key));
	if (tail.isEmpty()) { 
   
	    return nodes.get(nodes.firstKey());
	}
	return tail.get(tail.firstKey());
}

比较经典的一致性hash实现方案了,这里就不深入展开了。

说一下algo.hash(key) 这一步murmurHash为啥Hash碰撞少,性能快吧。

步骤1public long hash(byte[] key) { 
   
	return hash64A(key, 0x1234ABCD);
}
步骤2public static long hash64A(byte[] data, int seed) { 
   
	return hash64A(ByteBuffer.wrap(data), seed);
}
步骤3public static long hash64A(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;
}
hash64A(key, 0x1234ABCD);

long m = 0xc6a4a7935bd1e995L;
int r = 47;

murmurHash这个三个常量听说是Austin Appleby用大量测试数据肝出来的……
性能快应该是与大量使用位操作有关

里面的变化逻辑,自己比划吧,不一行行解释了;我表示看了跟没看一样……大神的世界,学都没法学,害……

最后给一个官方数据吧:

MurmurHash算法,自称超级快的hash算法,是FNV的4-5倍。官方数据如下:
OneAtATime – 354.163715 mb/sec
FNV – 443.668038 mb/sec
SuperFastHash – 985.335173 mb/sec
lookup3 – 988.080652 mb/sec
MurmurHash 1.0 – 1363.293480 mb/sec
MurmurHash 2.0 – 2056.885653 mb/sec

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/184172.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 无人机超远距离WiFi传输,CV5200无线通信模组,无线音视频传输方案「建议收藏」

    无人机超远距离WiFi传输,CV5200无线通信模组,无线音视频传输方案「建议收藏」在绝大多数任务场合都需要在远离现场的情况下,实时、可靠的观察或获取现场图像及视频,而此时无人机图传系统就会显现出它的重要作用。什么是无人机图传呢?将现场无人机所搭载的摄像机拍摄到的视频以无线方式实时传送到远距离后方的一种无线电子传输产品。因此无人机图传也被称为无人机的“眼睛”。智能cv5200双向无线通信系统,基于802.11无线通信标准,采用自身开发的LR-WiFi(远距离WiFi)私有协议,具备ML,MRC,LDPC,MIMO-OFDM等高级无线技术。具有传输距离远、可组网、抗干扰性强、

    2022年10月3日
    4
  • LINUX 环境变量总结

    LINUX 环境变量总结

    2021年8月22日
    54
  • vsftp怎么用_c++ ftp

    vsftp怎么用_c++ ftp一、vsftp以及安装服务端软件:vsftpd客户端软件:ftp端口号:20、21或指定范围内其他随机端口配置文件:vim/etc/vsftpd/vsftpd.conf#安装yuminstallvsftpdftp#开机自启systemctlenablevsftpd#启动systemctlstartvsftpd#查看端口开放情况netstat-antp二、工作模式,默认是主动port模式①主动模式(prot):FTP.

    2022年9月24日
    2
  • 在手写数字识别的例子中_手写识别

    在手写数字识别的例子中_手写识别1.概念介绍:图像识别(ImageRecognition)是指利用计算机对图像进行处理、分析和理解,以识别各种不同模式的目标和对像的技术。 图像识别的发展经历了三个阶段:文字识别、数字图像处理与识别、物体识别。机器学习领域一般将此类识别问题转化为分类问题。手写识别是常见的图像识别任务。计算机通过手写体图片来识别出图片中的字,与印刷字体不同的是,不同人的手写体风…

    2025年5月24日
    6
  • oracle分页基本语法[通俗易懂]

    oracle分页基本语法[通俗易懂]–分页:–mysql:limit–oracle:rownum伪列–伪列:在表结构中不存在的列–rowid伪列:用于唯一标识一行记录–rownum伪列:行号select*fromemp;–看不到行号–select*,rownumfromemp;–报错selecte.*,rownumfromempe;–正确的–rownum:行号是从1开始的,也…

    2022年5月28日
    51
  • 3.20 DAY3[通俗易懂]

    3.20 DAY3[通俗易懂]1.msg=’我叫%s,我看着像%r’%(‘太白’,’郭德纲’)print(msg)我叫太白,我看着像’郭德纲’句中出现引号,把%s替换成%r,可以打印出原来样式2.ASCII8位字节英文字母,数字,特殊字符unicode:万国码  python2:unicode默认是2个字节表示一个字符  python3:unicode统一是4个字节表示一个字符    创建初期16位字…

    2022年9月25日
    3

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号