这是我参与11月更文挑战的第16天,活动详情查看:2021最后一次更文挑战
一致性Hash算法
Hash冲突解决
开放寻址法
向前或向后找空闲位置存放
拉链法
在数组存储位置放一个链表
多哈希法
通过多个哈希算法进行哈希
建立公共溢出区
将哈希表分为基本表和溢出表两部分,凡是和基本表发生冲突的元素,一律填入溢出表
应用场景
-
请求负载均衡
nignx的ipHash策略
扫描二维码关注公众号,回复: 13171673 查看本文章 -
分布式存储
mysql, mongodb 或redis分布式存储
存在的问题
负载均衡场景时,如果服务器数目发生变化,session存储就会出现问题。
一致性Hash原理
顺时针将0-2的32次方-1的数编造成一个环, 将节点哈希的定位到哈希环, 对请求方进行哈希定位到哈希环,将请求落在按顺时针最近的节点。
节点缩容后, 原来路由到缩容节点的请求会路由在下一个节点上,只是这小部分收到影响, 避免了大量请求迁移。
节点扩容后, 原来路由到下个节点的请求会有一部分路由到新节点上, 只是这小部分收到影响, 避免了大量请求迁移。
虚拟节点
一致性Hash对于节点的影响,只有一小部分数据收到影响, 有较好的容错和扩展性。但是当节点数目太少后, 可能因为节点分布不均匀造成数目倾斜问题。为了解决这个问题,引入了虚拟节点。
虚拟节点方案是: 对每一个服务节点计算多个哈希, 每个计算结果都放置一个服务节点,也就是虚拟节点。请求落在虚拟节点时也就路由到真实节点上。
代码示例
一致性Hash
public void hash(){
String[] servers = new String[]{"192.168.0.1","192.168.0.2","192.168.0.3"};
SortedMap<Integer, String> hashServerMap = new TreeMap<>();
for(String server: servers){
int serverHash = Math.abs(server.hashCode());
hashServerMap.put(serverHash, server);
}
String[] clients = new String[]{"192.168.0.4","192.168.0.5","192.168.0.6"};
for(String client: clients){
int clientHash = Math.abs(client.hashCode());
SortedMap<Integer, String> map = hashServerMap.tailMap(clientHash);
if(map.isEmpty()){
Integer key = hashServerMap.firstKey();
}else {
Integer key = map.firstKey();
}
}
}
复制代码
虚拟节点Hash
public void hash(){
String[] servers = new String[]{"192.168.0.1","192.168.0.2","192.168.0.3"};
SortedMap<Integer, String> hashServerMap = new TreeMap<>();
int virtualCount =3;
for(String server: servers){
int serverHash = Math.abs(server.hashCode());
hashServerMap.put(serverHash, server);
for(int i=0; i< virtualCount; i++){
int virServerHash = Math.abs((server+"#"+i).hashCode());
hashServerMap.put(virServerHash, server);
}
}
String[] clients = new String[]{"192.168.0.4","192.168.0.5","192.168.0.6"};
for(String client: clients){
int clientHash = Math.abs(client.hashCode());
SortedMap<Integer, String> map = hashServerMap.tailMap(clientHash);
if(map.isEmpty()){
Integer key = hashServerMap.firstKey();
}else {
Integer key = map.firstKey();
}
}
}
复制代码
时钟同步
分布式集群中各个服务器节点都可以连接互联网
和国家授时中心/时间服务器同步, 通过定时任务执行
ntpdate -u ntp.api.bz #从一个时间服务器同步时间
复制代码
分布式集群中只有部分节点可以访问互联网
可以访问的节点通过ntpdate访问互联网,其他机器从可以访问的节点上访问
分布式节点都不能访问互联网
选取其中一个节点作为时间服务器, 其他服务器从这个节点访问
# 配置时间服务器
vim /etc/ntp.conf
# 如果有restrict default ignore, 注释掉
# 放开局域网同步功能, 172.17.0.0 是局域网网段
restrict 172.17.0.0 mask 255.255.255.0 nomodify notrap
server 127.127.1.0
fudge 127.127.1.0
service ntpd restart
chkconfig ntpd on
复制代码