1、平衡性(Balance):平衡性是指哈希的结果能够尽可能分布到所有的缓冲中去,这样可以使得所有的缓冲空间都得到利用。很多哈希算法都能够满足这一条件。
2、单调性(Monotonicity):单调性是指如果已经有一些内容通过哈希分派到了相应的缓冲中,又有新的缓冲加入到系统中。哈希的结果应能够保证原有已分配的内容可以被映射到原有的或者新的缓冲中去,而不会被映射到旧的缓冲集合中的其他缓冲区。?
3、分散性(Spread):在分布式环境中,终端有可能看不到所有的缓冲,而是只能看到其中的一部分。当终端希望通过哈希过程将内容映射到缓冲上时,由于不同终端所见的缓冲范围有可能不同,从而导致哈希的结果不一致,最终的结果是相同的内容被不同的终端映射到不同的缓冲区中。这种情况显然是应该避免的,因为它导致相同内容被存储到不同缓冲中去,降低了系统存储的效率。分散性的定义就是上述情况发生的严重程度。好的哈希算法应能够尽量避免不一致的情况发生,也就是尽量降低分散性。?
4、负载(Load):负载问题实际上是从另一个角度看待分散性问题。既然不同的终端可能将相同的内容映射到不同的缓冲区中,那么对于一个特定的缓冲区而言,也可能被不同的用户映射为不同 的内容。与分散性一样,这种情况也是应当避免的,因此好的哈希算法应能够尽量降低缓冲的负荷。代码如下:/** 把一个字符串映射为一个hash之后的数字* ?MurMurHash算法,是非加密HASH算法,性能很高,?* ?比传统的CRC32,MD5,SHA-1(这两个算法都是加密HASH算法,复杂度本身就很高,带来的性能上的损害也不可避免)??* ?等HASH算法要快很多,而且据说这个算法的碰撞率很低.??* ?http://murmurhash.googlepages.com/??*/ ??private static Long hash(String key) { ?? ? ?ByteBuffer buf = ByteBuffer.wrap(key.getBytes()); ?? ? ? ? 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;?? ? }??//映射key到真实节点 ?public void keyToNode(String key){ ?? ? ? ? // 沿环的顺时针找到一个虚拟节点 ?? ? ? ? SortedMap<Long, Node> tail = nodes.tailMap(this.hash(key));?? ? ? ? if (tail.size() == 0) { ?? ? ? ? ? ? return; ?? ? ? ? } ?? treeKey.put(hash(key), tail.get(tail.firstKey())); ?System.out.println(key+"(hash:"+hash(key)+")连接到主机->"+tail.get(tail.firstKey())); ?? ? } ??// 初始化一致性hash环 ??private void init() {?? ? ? ? nodes = new TreeMap<Long, Node>(); ?? ? ? ? treeKey = new TreeMap<Long, Node>(); ?? ? ? ? for (int i = 0; i != shards.size(); ++i) { // 每个真实机器节点都需要关联虚拟节点 ?? ? ? ? ? ? final Node shardInfo = shards.get(i); ???? ? ? ? ? ? for (int n = 0; n < NODE_NUM; n++) ?? ? ? ? ? ? ? ? // 一个真实机器节点关联NODE_NUM个虚拟节点 ?? ? ? ? ? ? ? ? nodes.put(hash("SHARD-" + shardInfo.name + "-NODE-" + n), shardInfo); ?? ? ? ? } ?? ? } ????public class Shard<Node> { // S类封装了机器节点的信息 ,如name、password、ip、port等 ???? ? static private TreeMap<Long, Node> nodes; // 虚拟节点到真实节点的映射 ?? ? static private TreeMap<Long,Node> treeKey; //key到真实节点的映射 ?? ? static private List<Node> shards = new ArrayList<Node>(); // 真实机器节点 ?? ? private final int NODE_NUM = 100; // 每个机器节点关联的虚拟节点个数 ?? ? boolean flag = false; ?? ? ??? ? public Shard(List<Node> shards) { ?? ? ? ? super(); ?? ? ? ? this.shards = shards; ?? ? ? ? init(); ?? ? } ?}
原文:http://gaojingsong.iteye.com/blog/2284795