zoukankan      html  css  js  c++  java
  • 一致性hash

    在缓存场景中,一致性hash算法避免了余数法在因为节点失效导致大面积缓存失效的问题。
    直接上代码,使用了Java自带的TreeMap, 参考了dubbo代码中的一致性hash负载
     1 package org.example;
     2 
     3 import java.nio.charset.StandardCharsets;
     4 import java.security.MessageDigest;
     5 import java.security.NoSuchAlgorithmException;
     6 import java.util.*;
     7 
     8 public class ConsistentHash<T> {
     9 
    10     private int VIRTUAL_NODE_NUM = 40;
    11     private final TreeMap<Long, T> circle = new TreeMap<>();
    12 
    13     public ConsistentHash(List<T> nodes, int VIRTUAL_NODE_NUM) {
    14         this.VIRTUAL_NODE_NUM = VIRTUAL_NODE_NUM;
    15         for (T node : nodes) {
    16             for (int i = 0; i < VIRTUAL_NODE_NUM; i++) {
    17                 byte[] digest = md5(node.toString() + i);
    18                 for (int h = 0; h < 4; h++) {
    19                     long m = hash(digest, h);
    20                     circle.put(m, node);
    21                 }
    22             }
    23         }
    24     }
    25 
    26     public T get(Object key) {
    27         if (circle.isEmpty()) {
    28             return null;
    29         }
    30         byte[] digest = md5(key.toString());
    31         long hash = hash(digest, 0);
    32         Map.Entry<Long, T> entry = circle.ceilingEntry(hash);
    33         if (entry == null) {
    34             entry = circle.firstEntry();
    35         }
    36         return entry.getValue();
    37     }
    38 
    39 
    40     private long hash(byte[] digest, int number) {
    41         return (((long) (digest[3 + number * 4] & 0xFF) << 24)
    42                 | ((long) (digest[2 + number * 4] & 0xFF) << 16)
    43                 | ((long) (digest[1 + number * 4] & 0xFF) << 8)
    44                 | (digest[number * 4] & 0xFF))
    45                 & 0xFFFFFFFFL;
    46     }
    47 
    48     private byte[] md5(String value) {
    49         MessageDigest md5;
    50         try {
    51             md5 = MessageDigest.getInstance("MD5");
    52         } catch (NoSuchAlgorithmException e) {
    53             throw new IllegalStateException(e.getMessage(), e);
    54         }
    55         md5.reset();
    56         byte[] bytes = value.getBytes(StandardCharsets.UTF_8);
    57         md5.update(bytes);
    58         return md5.digest();
    59     }
    60 }
  • 相关阅读:
    (Java实现) 洛谷 P1106 删数问题
    (Java实现) 洛谷 P1603 斯诺登的密码
    (Java实现) 洛谷 P1036 选数
    (Java实现) 洛谷 P1012 拼数
    (Java实现) 洛谷 P1028 数的计算
    (Java实现) 洛谷 P1553 数字反转(升级版)
    (Java实现) 洛谷 P1051 谁拿了最多奖学金
    (Java实现) 洛谷 P1051 谁拿了最多奖学金
    (Java实现) 洛谷 P1106 删数问题
    目测ZIP的压缩率
  • 原文地址:https://www.cnblogs.com/beyondbit/p/13222530.html
Copyright © 2011-2022 走看看