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.按照.


Jetbrains全系列IDE稳定放心使用

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

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

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

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

首先是hash函数,在Jedis中有两种Hash算法可供选择,分别是MurMurHash和MD5. 按照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碰撞少,性能快吧。

步骤1:
public long hash(byte[] key) { 
   
	return hash64A(key, 0x1234ABCD);
}
步骤2:
public static long hash64A(byte[] data, int seed) { 
   
	return hash64A(ByteBuffer.wrap(data), seed);
}
步骤3:
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;
}
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)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • AIRFLow_overflow百度百科

    AIRFLow_overflow百度百科1、什么是AirflowAirflow是一个Airbnb的Workflow开源项目,使用Python编写实现的任务管理、调度、监控工作流平台。Airflow是基于DAG(有向无环图)的任务管理系统,可以简单理解为是高级版的crontab,但是它解决了crontab无法解决的任务依赖问题。与crontab相比Airflow可以方便查看任务的执行状况(执行是否成功、执行时间、执行依赖等),可追踪任务历史执行情况,任务执行失败时可以收到邮件通知,查看错误日志。2、Airflow与同类产品的

    2022年10月24日
  • 【PCIe】配置空间

    【PCIe】配置空间介绍PCI/PCIe配置空间。

    2022年6月17日
  • 令人比较失落的IT圈子-关于华为裁员

    令人比较失落的IT圈子-关于华为裁员早在几年前就有人说过程序员在35岁以后如果不做管理就很难混了,如今由于近日的华为事件被炒得沸沸扬扬,显然让这多年前人们的猜测变成了现实,我今年也正好到了这个该“退休”的年龄,所以就想趁机悔恨一番。首先,澄清的一点就是,我并无意诋毁这个IT行业,我只是希望大家可以更加清除的认清这个行业。       什么叫做管理,在程序员的思维里,做管理其实很简单,就是从写代码到不写代码,哪怕是写PPT,只要不写

    2022年7月25日
  • C++编程工具(java常用工具)

    给c++程序员的一份礼物-常用工具集■…开发环境  —->Turboc  DOS时代c语言开发的经典工具,目前适合两类人使用:c语言beginner(尤其是学生一族),具有怀旧情节的专业人士:)  —->VisualC++6.0/7.0  稳定而强大的IDE开发环境,具有丰富的调试功能,定制宏的功能也是其一大特色。Microsoft的经典之作,功能强大自不必言说

    2022年4月13日
  • xshell安装步骤_Xshell6

    xshell安装步骤_Xshell6开发环境部署目的:利用ssh远程登陆服务器(在windows系统下远程连接linux)下载XSHELL7XSHELL7下载网址:https://www.netsarang.com/zh/xshell/点击“下载”点击“免费授权界面”以上是XSHELL7的下载过程然后找到右键“以管理员身份运行”一上来会出现这种错误,先点击“是(Y)”过程中一直点击“下一步”,以及“我同意”类似的,然后选择个安装路径就可以没啥特殊的。到最后一切顺利的话会显示下面这样的界面一般通向成功的道

    2022年9月9日
  • 2018年NGINX最新版高级视频教程[通俗易懂]

    2018年NGINX最新版高级视频教程

    2022年2月9日

发表回复

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

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