源地址哈希Hash算法
源地址哈希的思想是获取客户端访问的 IP 地址值,通过哈希函数计算得到一个数值,用该数值对服务器列表的大小进行取模运算,得到的结果边是要访问的服务器的序号。采用哈希法进行负载均衡,同一 IP 地址的客户端,当后端服务器列表不变时,它每次都会映射到同一台后端服务器进行访问
public class RandomTest {
static List<String> list = Arrays.asList("192.168.0.101", "192.168.0.102", "192.168.0.103", "192.168.0.104");
public static void main(String[] args) throws InterruptedException {
while (true) {
System.err.println(get("10.168.0.101"));
TimeUnit.SECONDS.sleep(1);
}
}
private static synchronized String get(String ip) {
// 拷贝服务列表避免出现由于服务器上线和下线导致的并发问题
List<String> result = new ArrayList<>();
result.addAll(list);
int hashCode = System.identityHashCode(ip);
int size = result.size();
int index = hashCode % size;
return result.get(index);
}
}
通过参数传入的客户端 remoteip 参数,取得它的哈希值,对服务器列表的大小取模,结果便是选用的服务器在服务器列表中的索引值。该算法保证了相同的客户端 IP 地址将会被“哈希”到同一台后端服务器,直到后端服务器列表变更。根据此特性可以在服务消费者与服务提供者之间建立有状态的 session 会话
hash算法中,存在以下的几个问题
1.当一台服务器宕机了或者新添加一台机器之后,这个时候hashCode % servers.size()需要重新计算hash值, 如果在缓存的环境中,所有的请求都会涌向数据库服务器,给数据库服务器带来巨大的压力,可能导致整个系统不可用,形成雪崩效应;
2 .当新增了一台性能强的机器后,利用上述的hash算法无法让,新增的性能强的服务器多承担压力;
基于上面的几个问题,提出了hash算法的改进:一致性hash算法