Skip to content

Commit

Permalink
分布式ID雪花算法调整
Browse files Browse the repository at this point in the history
  • Loading branch information
dolyw committed May 18, 2023
1 parent 7808071 commit 942283c
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,6 @@ public IdWorker(long workerId, long datacenterId, long sequence) {
}
System.out.printf("worker starting. timestamp left shift %d, datacenter id bits %d, worker id bits %d, sequence bits %d, workerid %d",
timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits, workerId);
System.out.println();

this.workerId = workerId;
this.datacenterId = datacenterId;
Expand Down Expand Up @@ -184,6 +183,7 @@ private long timeGen() {
*/
public static void main(String[] args) throws Exception {
IdWorker worker = new IdWorker(0L, 0L, 0L);
System.out.println();
for (int i = 0; i < 10; i++) {
Thread.sleep(1000L);
System.out.println(worker.nextId());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,19 +58,19 @@ public class IdWorkerPatch {
* @param sequence
*/
public IdWorkerPatch(long workerId, long datacenterId, long sequence) {
logger.info("SnowFlake Starting. timestampLeftShift {}, datacenterIdBits {}, workerIdBits {}, sequenceBits {}",
timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits);
// sanity check for workerId
if (workerId > maxWorkerId || workerId < 0L) {
throw new IllegalArgumentException(String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0L) {
throw new IllegalArgumentException(String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
}
logger.info("worker starting. timestamp left shift {}, datacenter id bits {}, worker id bits {}, sequence bits {}, workerid {}",
timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits, workerId);

this.workerId = workerId;
this.datacenterId = datacenterId;
this.sequence = sequence;
logger.info("SnowFlake Ending. workerId {}, datacenterId {}, sequence {}", workerId, datacenterId, sequence);
}

/**
Expand Down Expand Up @@ -228,7 +228,7 @@ private long timeGen() {
* @throws Exception
*/
public static void main(String[] args) throws Exception {
IdWorkerPatch idWorkerPatch = new IdWorkerPatch(15L, 15L, 0L);
IdWorkerPatch idWorkerPatch = new IdWorkerPatch(19L, 31L, 2L);
for (int i = 0; i < 10; i++) {
Thread.sleep(1000L);
logger.info("{}", idWorkerPatch.nextId());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.snow;

import cn.hutool.core.util.RandomUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand Down Expand Up @@ -59,58 +60,23 @@ public class IdWorkerPatch2 {
*/
private long sequence;

private static volatile InetAddress LOCAL_ADDRESS = null;
private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$");

/**
* 构造函数
*/
public IdWorkerPatch2() {
logger.info("SnowFlake Starting. timestampLeftShift {}, datacenterIdBits {}, workerIdBits {}, sequenceBits {}",
timestampLeftShift, datacenterIdBits, workerIdBits, sequenceBits);
this.datacenterId = getDatacenterId();
this.workerId = getMaxWorkerId(datacenterId);
}

/**
* 基于网卡MAC地址计算余数作为数据中心
* <p>
* 可自定扩展
*/
protected long getDatacenterId() {
long id = 0L;
try {
NetworkInterface network = NetworkInterface.getByInetAddress(getLocalAddress());
if (null == network) {
id = 1L;
} else {
byte[] mac = network.getHardwareAddress();
if (null != mac) {
id = ((0x000000FF & (long) mac[mac.length - 2]) | (0x0000FF00 & (((long) mac[mac.length - 1]) << 8))) >> 6;
id = id % (maxDatacenterId + 1);
}
}
} catch (Exception e) {
logger.warn(" getDatacenterId: " + e.getMessage());
this.workerId = getMaxWorkerId(this.datacenterId);
logger.info("SnowFlake Running. workerId {}, datacenterId {}, sequence {}", workerId, datacenterId, sequence);
// sanity check for workerId
if (this.workerId > maxWorkerId || this.workerId < 0L) {
this.workerId = RandomUtil.randomLong(0, 31);
}

return id;
}

/**
* 基于 MAC + PID 的 hashcode 获取16个低位
* <p>
* 可自定扩展
*/
protected long getMaxWorkerId(long datacenterId) {
StringBuilder mpId = new StringBuilder();
mpId.append(datacenterId);
String name = ManagementFactory.getRuntimeMXBean().getName();
if (name != null && name.length() > 0) {
// GET jvmPid
mpId.append(name.split("@")[0]);
if (this.datacenterId > maxDatacenterId || this.datacenterId < 0L) {
this.datacenterId = RandomUtil.randomLong(0, 31);
}

// MAC + PID 的 hashcode 获取16个低位
return (mpId.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
logger.info("SnowFlake Ending. workerId {}, datacenterId {}, sequence {}", workerId, datacenterId, sequence);
}

/**
Expand Down Expand Up @@ -173,6 +139,16 @@ protected long getMaxWorkerId(long datacenterId) {
*/
private long lastSequence = 0L;

/**
* IP正则表达式
*/
private static final Pattern IP_PATTERN = Pattern.compile("\\d{1,3}(\\.\\d{1,3}){3,5}$");

/**
* 本机地址
*/
private static volatile InetAddress LOCAL_ADDRESS = null;

/**
* 获得下一个ID (该方法是线程安全的)
*
Expand Down Expand Up @@ -251,20 +227,57 @@ private long tilNextMillis(long lastTimestamp) {
}

/**
* Find first valid IP from local network card
*
* @return first valid local IP
* 基于网卡MAC地址计算余数作为数据中心
* <p>
* 可自定扩展
*/
public static InetAddress getLocalAddress() {
if (LOCAL_ADDRESS != null) {
return LOCAL_ADDRESS;
protected long getDatacenterId() {
try {
long id = 0L;
if (LOCAL_ADDRESS == null) {
LOCAL_ADDRESS = getLocalAddress();
}
NetworkInterface network = NetworkInterface.getByInetAddress(LOCAL_ADDRESS);
byte[] mac = network.getHardwareAddress();
if (null != mac) {
id = ((0x000000FF & (long) mac[mac.length - 2]) | (0x0000FF00 & (((long) mac[mac.length - 1]) << 8))) >> 6;
id = id % (maxDatacenterId + 1);
}
return id;
} catch (Exception e) {
logger.warn("getDatacenterId: " + e.getMessage());
return -1L;
}
}

LOCAL_ADDRESS = getLocalAddress0();
return LOCAL_ADDRESS;
/**
* 基于 MAC + PID 的 hashcode 获取16个低位
* <p>
* 可自定扩展
*/
protected long getMaxWorkerId(long datacenterId) {
try {
StringBuilder mpId = new StringBuilder();
mpId.append(datacenterId);
String name = ManagementFactory.getRuntimeMXBean().getName();
if (name != null && name.length() > 0) {
// GET jvmPid
mpId.append(name.split("@")[0]);
}
// MAC + PID 的 hashcode 获取16个低位
return (mpId.toString().hashCode() & 0xffff) % (maxWorkerId + 1);
} catch (Exception e) {
logger.warn("getMaxWorkerId: " + e.getMessage());
return -1L;
}
}

private static InetAddress getLocalAddress0() {
/**
* Find first valid IP from local network card
*
* @return first valid local IP
*/
private static InetAddress getLocalAddress() {
InetAddress localAddress = null;
try {
localAddress = InetAddress.getLocalHost();
Expand Down Expand Up @@ -305,11 +318,13 @@ private static InetAddress getLocalAddress0() {
return localAddress;
}

/**
* local IP Valid
*/
private static boolean isValidAddress(InetAddress address) {
if (address == null || address.isLoopbackAddress()) {
return false;
}

String name = address.getHostAddress();
return (name != null && !"0.0.0.0".equals(name) && !"127.0.0.1".equals(name) && IP_PATTERN.matcher(name).matches());
}
Expand Down

0 comments on commit 942283c

Please sign in to comment.