赣州网站制作找哪家好,营销型网站的作用是,做知乎网站社区要多少钱,关联词有哪些五年级Hash算法的问题
今天看下一致性hash#xff0c;常见的负载均衡可能使用过hash#xff0c;比如nginx中#xff0c;如果使用session最简单就是通过hash#xff0c;比如根据用户的请求ip进行hash#xff0c;让不同用户的请求打到同一台服务器#xff0c;这样状态处理起来最…Hash算法的问题
今天看下一致性hash常见的负载均衡可能使用过hash比如nginx中如果使用session最简单就是通过hash比如根据用户的请求ip进行hash让不同用户的请求打到同一台服务器这样状态处理起来最简单对于session来说如果现在重新上线了一台服务器导致了所有请求hash之后的得到的服务器地址变了也就是session可能全部丢失了即使用户对应的服务器并没有重启但是因为服务器数量发生了变化导致分配到的服务器有所改变这就是hash带来的问题。
一致性hash的使用场景
那么一致性hash就是解决hash的这些问题诞生的一致性hash常见的落地场景可以想象下redis的数据redis是设计了16384的hash槽每个数据来的根据key做hash然后分配到固定的hash槽redis需要集群分片的时候不具体区分每一个key是去分hash槽然后新增节点的之后只需要分配给其一些hash槽然后转移对应的数据过去即可删除节点的时候也是只需要把这个节点的数据分配给其他节点即可没涉及到的数据不会有影响。
一致性hash概念
所以一致性hash的定义也就是我先分配很多的hash节点然后我每一个实际的提供服务的节点负责一部分的hash节点hash节点是固定的比实际节点大很多然后上下线节点只需要调整实际节点负责的节点数量即可。 实际大家说的hash环的问题就是说我的很多虚拟节点hash节点组成的环然后让实际的提供服务的节点尽量均匀的落到hash节点上后续的请求或者说数据按照hash之后也落到虚拟hash节点上这个节点可能并没有实际的服务节点他就可以向后遍历找到对应提供服务的节点也就代表着一个实际提供服务的节点负责他前面的所有虚拟节点直到遇到上一个实际服务的节点。
一致性hash需要处理的问题
这样可能存在的问题就是实际服务提供者的hash结果倾斜怎么办也就是所有节点都落到一片去了这样前面的节点就需要负责绝大部分的请求还是要想办法让其尽量均匀也就是要给每个实际节点可以多种hash算法生成多个节点让其尽可能均匀的分布到环上让请求均匀分配到节点上 来看下dubbo怎么具体实现的这个问题,关键代码如下 ConsistentHashSelector(ListInvokerT invokers, String methodName, int identityHashCode) {// treeMap方便向上取this.virtualInvokers new TreeMapLong, InvokerT();this.identityHashCode identityHashCode;URL url invokers.get(0).getUrl();// 虚拟节点数量默认160这里是一个服务虚拟出来的节点this.replicaNumber url.getMethodParameter(methodName, HASH_NODES, 160);String[] index COMMA_SPLIT_PATTERN.split(url.getMethodParameter(methodName, HASH_ARGUMENTS, 0));argumentIndex new int[index.length];for (int i 0; i index.length; i) {argumentIndex[i] Integer.parseInt(index[i]);}for (InvokerT invoker : invokers) {String address invoker.getUrl().getAddress();for (int i 0; i replicaNumber / 4; i) {// 这里也就是一个服务默认先虚拟160个节点byte[] digest Bytes.getMD5(address i);for (int h 0; h 4; h) {// 分别4位4位的进行运算也就是放四个值每个invoker使用不同位数得到的hash值long m hash(digest, h);virtualInvokers.put(m, invoker);}}}}// hash算法对其每一位进行处理想要均匀private long hash(byte[] digest, int number) {return (((long) (digest[3 number * 4] 0xFF) 24)| ((long) (digest[2 number * 4] 0xFF) 16)| ((long) (digest[1 number * 4] 0xFF) 8)| (digest[number * 4] 0xFF)) 0xFFFFFFFFL;}// 具体的选择算法也就是hash结果选择关键结构逻辑参考构造方法public InvokerT select(Invocation invocation) {byte[] digest Bytes.getMD5(RpcUtils.getMethodName(invocation));return selectForKey(hash(digest, 0));}// 具体的选择方法private InvokerT selectForKey(long hash) {// 向上取TreeMap的方法Map.EntryLong, InvokerT entry virtualInvokers.ceilingEntry(hash);if (entry null) {// 没取到的取第一个也就是造成一个环的概念数据落到最后一个节点后面entry virtualInvokers.firstEntry();}return entry.getValue();}总结
可以看到dubbo为了处理数据倾斜的问题默认虚拟160个节点然后根据地址加上对应的值然后又采用每一位数字的hash算法进行散列得到的值采用的数据结构就是TreeMap是一个可排序的Map可以直接向上取ceilingEntry数据过来之后hash得到值然后取对应的节点TreeMap兼具一定的查找性能能