相信做过互联网应用的都知道,如何很好的做到横向扩展,其实是个蛮难的话题,缓存可横向扩展,如果采用简单的取模,余数方式的部署,基本是无法做到后期的扩展的,数据迁移及分布都是问题,举个例子:

假设采用取模的方式来实现的分布式缓存,缓存节点为10个,这时候所有的缓存分布在10个节点上,任意一个节点down掉都会导致其他的缓存需要重新分布,从而会让所有缓存失效,这种在互联网应用上基本上是绝不允许出现的,那么如何来解决这个问题呢?!

一般目前互联网上的很多开源应用都是在客户端采用一致性hash来实现分布的,一致性hash又称环状hash,任意一节点出现问题不会影响全局数据有效性,具体的原理可以参考这里:一致哈希

下面简单贴出一致性hash的java实现参考:

import java.nio.ByteBuffer;
import java.nio.ByteOrder; /**
* This is a very fast, non-cryptographic hash suitable for general hash-based
* lookup. See http://murmurhash.googlepages.com/ for more details.
* <p/>
* <p>
* The C version of MurmurHash 2.0 found at that site was ported to Java by
* Andrzej Bialecki (ab at getopt org).
* </p>
*/
public class MurmurHash implements Hashing {
/**
* Hashes bytes in an array.
*
* @param data
* The bytes to hash.
* @param seed
* The seed for the hash.
* @return The 32 bit hash of the bytes in question.
*/
public static int hash(byte[] data, int seed) {
return hash(ByteBuffer.wrap(data), seed);
} /**
* Hashes bytes in part of an array.
*
* @param data
* The data to hash.
* @param offset
* Where to start munging.
* @param length
* How many bytes to process.
* @param seed
* The seed to start with.
* @return The 32-bit hash of the data in question.
*/
public static int hash(byte[] data, int offset, int length, int seed) {
return hash(ByteBuffer.wrap(data, offset, length), seed);
} /**
* Hashes the bytes in a buffer from the current position to the limit.
*
* @param buf
* The bytes to hash.
* @param seed
* The seed for the hash.
* @return The 32 bit murmur hash of the bytes in the buffer.
*/
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));
}
}
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);
}

一致性Hash在分布式应用中使用的很多,memcached,redis等等。

浅谈一致性hash的更多相关文章

  1. 浅谈一致性Hash原理及应用

    在讲一致性Hash之前我们先来讨论一个问题. 问题:现在有亿级用户,每日产生千万级订单,如何将订单进行分片分表? 小A:我们可以按照手机号的尾数进行分片,同一个尾数的手机号写入同一片/同一表中. 大佬 ...

  2. 浅谈字符串Hash

    浅谈字符串Hash 本篇随笔讲解Hash(散列表)的一个重要应用:字符串Hash. 关于Hash Hash是一种数据结构,叫做Hash表(哈希表),也叫散列表.关于Hash的实现,其实与离散化颇为类似 ...

  3. 浅尝一致性Hash原理

    写在前面 在解决分布式系统中负载均衡的问题时候可以使用Hash算法让固定的一部分请求落到同一台服务器上,这样每台服务器固定处理一部分请求(并维护这些请求的信息),起到负载均衡的作用.但是普通的余数ha ...

  4. 浅谈一致性哈希(My转)

    一致性哈希(Consistent hashing)算法是由 MIT 的Karger 等人与1997年在一篇学术论文(<Consistent hashing and random trees: d ...

  5. 浅谈NTLM Hash

    认识Windows Hash 早期SMB协议在网络上传输明文口令.后来出现LAN Manager 挑战/响应验证机制(LM),其很容易破解,因此微软提出了WindowsNT挑战/响应验证机制(NTLM ...

  6. $.ajax()方法详解 ajax之async属性 【原创】详细案例解剖——浅谈Redis缓存的常用5种方式(String,Hash,List,set,SetSorted )

    $.ajax()方法详解   jquery中的ajax方法参数总是记不住,这里记录一下. 1.url: 要求为String类型的参数,(默认为当前页地址)发送请求的地址. 2.type: 要求为Str ...

  7. [转帖]浅谈分布式一致性与CAP/BASE/ACID理论

    浅谈分布式一致性与CAP/BASE/ACID理论 https://www.cnblogs.com/zhang-qc/p/6783657.html ##转载请注明 CAP理论(98年秋提出,99年正式发 ...

  8. Hash表从了解到深入(浅谈)

    · Hasn表,将一个数据进行Value化,再进行一个映射关系到Key直接进行访问的一个数据结构,这样可以通过直接的计算进行数据的访问和插入.关于Hash表的基本概念这里就不一一叙述,可以通过百度了解 ...

  9. 【转】浅谈Java中的hashcode方法(这个demo可以多看看)

    浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地方都会利用到hash表来提高查找效率.在Java的Object类中有一个方法: public native i ...

随机推荐

  1. 【分块】bzoj3226 [Sdoi2008]校门外的区间

    题解见 : http://blog.csdn.net/iamzky/article/details/41088151 ORZ ZKY 2个懒标记:是否翻转,覆盖成了什么. 怎么处理一个块上有两个标记的 ...

  2. Java多线程——AQS框架源码阅读

    AQS,全称AbstractQueuedSynchronizer,是Concurrent包锁的核心,没有AQS就没有Java的Concurrent包.它到底是个什么,我们来看看源码的第一段注解是怎么说 ...

  3. 在iPhone上取消APP订阅

    1.在iPhone上打开APP Store,在精品推荐那个界面滚动到底部. 2.点击Apple ID那一栏,如图: 3.点击查看Apple ID,如图: 4.点击管理,如图: 5.关掉此选项,如图: ...

  4. coco2dx-2.2.2 win32启动过程(opengl 和 窗口大小初始化部分) - 学习笔记 1

    因为最近要做不同分辩率的适配,所于看了下引擎这方面的代码,记录一下当是学习笔记,cocos2d-x 版本 2.2.2 , 例子是samples\Cpp\TestCpp下的 TestCpp. 先看下ma ...

  5. 你真的了解try{ return }finally{}中的return?(转载)

    发现一篇有意思的博文,分享一下 谁能给我我解释一下这段程序的结果为什么是:2.而不是:3 代码如下: class Test { public int aaa() { int x = 1; try { ...

  6. jquery给input标签添加data-options属性

    //原生JS实现document.getElementById('startPrice').setAttribute("data-options", "required: ...

  7. [ubuntu Setup] ubuntu 14.10 安装 JDK

    from :  http://www.cnblogs.com/plinx/archive/2013/06/01/3113106.html 1.到 Sun 的官网下载 http://www.oracle ...

  8. MVC Movie App

    ylbtech- ASP.NET MVC:MVC Movie App 功能描述:MVC Movie App 2,TechnologyAndTheEnvironment(技术与环境) 操作系统: win ...

  9. 增强学习--Sarsa算法

    Sarsa算法 实例代码 import numpy as np import random from collections import defaultdict from environment i ...

  10. POJ 3020 Antenna Placement 最大匹配

    Antenna Placement Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 6445   Accepted: 3182 ...