有人知道网站怎么做吗,中国建设银行的网站用户名是什么意思,wordpress滑动,百度站长如何验证网站Hash算法的应用场景
请求的负载均衡 Nginx的ip_hash策略可以在客户端ip不发生变化的情况下#xff0c;将其发出的请求始终路由到同一个目标服务器上#xff0c;实现会话粘滞#xff0c;避免处理session共享问题。
如果没有ip_hash策略#xff0c;可以通过维护一张映射表的…Hash算法的应用场景
请求的负载均衡 Nginx的ip_hash策略可以在客户端ip不发生变化的情况下将其发出的请求始终路由到同一个目标服务器上实现会话粘滞避免处理session共享问题。
如果没有ip_hash策略可以通过维护一张映射表的方式来实现会话粘滞 映射表存储的是客户端ip或者session与具体目标服务器的映射关系 ip,server 缺点 客户端很多的情况下映射表非常大浪费内存空间客户端上下线、目标服务器上下线都会导致重新维护映射表维护成本大 如果使用Hash算法可以对ip或者session计算hash值hash值与服务器数量进行取模运算得到的值就是当前请求应该被路由到的服务器编号。由此同一个ip发送过来的请求就可以路由到同一个目标服务器实现会话粘滞。
分布式存储 有 Redis1、Redis2、Redis3 三台Redis服务器可以针对key进行hash处理 Hash(key)%3 index 使用余数锁定存储的具体服务器节点。
普通Hash算法存在的问题
以ip_hash为例假定用户ip固定不变当后端服务器有一个宕机数量由3变为2那么之前所有用户的求模都需要重新计算。 如果在生产环境中后台服务器有很多台客户端也有很多个出现这种问题的影响是很大的。服务器的扩缩容都会出现这样的问题大量的用户请求被路由到其他的目标服务器处理用户在原来服务器的会话都将丢失。
普通Hash算法
// 定义客户端IP
String[] clients {192.168.31.121, 192.168.3.21, 192.168.1.11};// 定义服务器数量
int server 5;// hash(ip) % server数量 index
for (String client : clients) {int hashCode Math.abs(client.hashCode());int index hashCode % server;System.out.println(客户端\t client \t 分配到了服务器 (index 1) 上);
}一致性Hash算法的思路
首先有一条直线直线开头和结尾分别定为1和232-1,这相当于一个地址对于这样一条直线首尾相连构成一个闭环这样的圆环称为Hash环把服务器IP或者主机名求Hash值然后对应到Hash环上针对客户端IP求Hash值对应到环上的某个位置然后按照顺时针的方向找最近的服务器节点 缩容 假设将节点3下线原来路由到3的客户端请求重新路由到节点4对于其他客户端没有影响只是这一小部分受到影响 请求的迁移量达到了最小这样的算法对于分布式集群来说非常合适避免了大量请求转移。 扩容 新增节点5之后原来路由到节点3的部分客户端路由到了节点5上对于其他客户端没有影响只是这一小部分受到影响 代码如下
// 定义服务器IP
String[] servers {192.168.31.121, 192.168.3.21, 192.168.1.11, 12.168.31.121, 192.138.3.21, 192.68.1.11};
// 定义客户端IP
String[] clients {12.16.31.121, 12.18.3.1, 19.16.1.11};
// 计算服务器的Hash并放到排序的Map中
SortedMapInteger,String hashServerMap new TreeMap();
for (String server : servers) {int hashCode Math.abs(server.hashCode());hashServerMap.put(hashCode,server);
}
// 求客户端IP的Hash取出对应的服务器
for (String client : clients) {int clientHash Math.abs(client.hashCode());SortedMapInteger, String tailedMap hashServerMap.tailMap(clientHash);// 取出Hash环上的第一台服务器Integer firstKey;if (tailedMap.isEmpty()){firstKey hashServerMap.firstKey();}else {firstKey tailedMap.firstKey();}System.out.println(客户端IP\t client \t被路由到了服务器\t hashServerMap.get(firstKey));
}存在的问题及解决方法
如上所述每一台服务器负责一段一致性Hash算法对于节点的增加都只需要重定位环空间的一小部分数据具有较好的容错性和可扩展性。
一致性Hash算法在服务节点太少时容易因节点分部不均匀造成数据倾斜问题。例如只有两台服务器这两台服务器在环上的分部十分靠近导致某个节点只负责非常小的一段大量的请求落在了另外一个节点上导致数据倾斜。为了解决这种方法一致性Hash算法引入了虚拟节点机制即对每一个服务节点计算多个Hash每个计算结果都放置一个此服务节点称为虚拟节点。具体做法可以在服务器IP或者主机名后增加编号来实现例如 “节点1的ip#1” “节点1的ip#2” “节点1的ip#3”……形成多个虚拟节点当客户端被路由到虚拟节点的时候其实是被路由到该虚拟节点所对应的真实节点。
代码如下
// 定义服务器IP
String[] servers {192.168.31.121, 192.168.3.21, 192.168.1.11, 12.168.31.121, 192.138.3.21, 192.68.1.11};
// 定义客户端IP
String[] clients {12.16.31.121, 12.18.3.1, 19.16.1.11};SortedMapInteger, String serverHash new TreeMap();int virtualNodeCount 3;
// 开始计算服务器的Hash
for (String server : servers) {int hash Math.abs(server.hashCode());serverHash.put(hash, server);// 设置虚拟节点for (int i 0; i virtualNodeCount; i) {int virtualNodeHash Math.abs((server # i).hashCode());serverHash.put(virtualNodeHash, 虚拟节点 i 映射过来的请求 server);}
}System.out.println(serverHash.size());
// 计算客户端请求的服务器Hash
for (String client : clients) {int clientHash Math.abs(client.hashCode());SortedMapInteger, String tailedMap serverHash.tailMap(clientHash);if (tailedMap.isEmpty()) {Integer firstKey serverHash.firstKey();System.out.println(客户端 client \t\t路由到了 \t serverHash.get(firstKey));} else {Integer firstKey tailedMap.firstKey();System.out.println(客户端 client \t\t路由到了 \t serverHash.get(firstKey));}
}