雪花算法的机器id重复-创新互联
通常雪花算法的机器id是根据网络ip地址计算得到的一个long类型值。从阿里的nacos扒下来的雪花算法实现:
创新互联公司专业为企业提供湛河网站建设、湛河做网站、湛河网站设计、湛河网站制作等企业网站建设、网页设计与制作、湛河企业网站模板建站服务,十年湛河做网站经验,不只是建网站,更提供有价值的思路和整体网络服务。static {InetAddress address = NetUtil.getLocalAddress0();
if (address == null) {throw new IllegalStateException("Cannot get LocalHost InetAddress, please check your network!");
}
byte[] ipAddressByteArray = address.getAddress();
hostIp = address.getHostAddress();
workerId = (((ipAddressByteArray[ipAddressByteArray.length - 2] & 0B11)<< Byte.SIZE) + (
ipAddressByteArray[ipAddressByteArray.length - 1] & 0xFF));
log.info("snowflower workerId: {}", workerId);
}
getLocalAddress0方法的实现 NetworkInterface的getInetAddress对象,返回的是Inet6Address
public static InetAddress getLocalAddress0() {InetAddress localAddress = null;
// @since 2.7.6, choose the {@link NetworkInterface} first
try {NetworkInterface networkInterface = findNetworkInterface();
Enumerationaddresses = networkInterface.getInetAddresses();
while (addresses.hasMoreElements()) {OptionaladdressOp = toValidAddress(addresses.nextElement());
if (addressOp.isPresent()) {try {if (addressOp.get().isReachable(100)) {return addressOp.get();
}
} catch (IOException e) {// ignore
}
}
}
} catch (Throwable e) {log.warn("{}", e.getMessage(), e);
}
try {localAddress = InetAddress.getLocalHost();
OptionaladdressOp = toValidAddress(localAddress);
if (addressOp.isPresent()) {return addressOp.get();
}
} catch (Throwable e) {log.warn("{}", e.getMessage(), e);
}
return localAddress;
}
getValidNetworkInterfaces方法的实现:
返回53个主机上的网络接口,名字是lo eth1 eth2 … net0 net1 wlan0等等。这些ip地址都是ipv6的。NetworkInterface类。
private static ListgetValidNetworkInterfaces() throws SocketException {ListvalidNetworkInterfaces = new LinkedList<>();
Enumerationinterfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {NetworkInterface networkInterface = interfaces.nextElement();
validNetworkInterfaces.add(networkInterface);
}
return validNetworkInterfaces;
}
findNetworkInterface方法的实现:
public static NetworkInterface findNetworkInterface() {ListvalidNetworkInterfaces = Collections.emptyList();
try {validNetworkInterfaces = getValidNetworkInterfaces();
} catch (Throwable e) {log.warn("{}", e.getMessage(), e);
}
for (NetworkInterface networkInterface : validNetworkInterfaces) {Enumerationaddresses = networkInterface.getInetAddresses();
while (addresses.hasMoreElements()) {OptionaladdressOp = toValidAddress(addresses.nextElement());
if (addressOp.isPresent()) {try {if (addressOp.get().isReachable(100)) {return networkInterface;
}
} catch (IOException e) {// ignore
}
}
}
}
return validNetworkInterfaces.get(0);
}
上面的代码含义是获取主机的所有网络接口。然后从第一个网络接口开始,如果可访问(isReachable(100)),就将这个IP地址返回。相同的ip地址必然产生相同的机器id(workerId)
今天的坑是因为服务器不同,ipv4地址不同,但是ipv6地址相同。使用了ipv6地址生成的workerId,就必然相同了。影响了雪花算法。以及其它用workerid作分布式的业务。
因为只有测试环境的ipv6地址都相同;线上的不会相同,所以为了测试,在IDEA edit configuration里加上的-Djava.net.preferIPv4Stack=true,这时看到所有的接口用的ipv4。
例如lo的地址,不加这个option,是16个字节的0::1;加了就是4个字节的127.0.0.1
后期改进,可以先从文件读取workerId, 如果没有再生成,并保存到文件中。避免主机ip地址变更导致的workerid变更问题。
你是否还在寻找稳定的海外服务器提供商?创新互联www.cdcxhl.cn海外机房具备T级流量清洗系统配攻击溯源,准确流量调度确保服务器高可用性,企业级服务器适合批量采购,新人活动首月15元起,快前往官网查看详情吧
文章题目:雪花算法的机器id重复-创新互联
URL地址:http://ybzwz.com/article/deooii.html