diff --git a/code/base-project/base-springboot/src/main/java/cn/g3soft/BaseApplication.java b/code/base-project/base-springboot/src/main/java/cn/g3soft/BaseApplication.java index 84ce341f..3157fd24 100644 --- a/code/base-project/base-springboot/src/main/java/cn/g3soft/BaseApplication.java +++ b/code/base-project/base-springboot/src/main/java/cn/g3soft/BaseApplication.java @@ -12,7 +12,6 @@ import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; }) public class BaseApplication { public static void main(String[] args) { - System.out.println(SnowflakeIdUtils.nextId()); SpringApplication.run(BaseApplication.class,args); } } diff --git a/code/base-project/base-springboot/src/main/java/cn/g3soft/utils/SnowflakeIdUtils.java b/code/base-project/base-springboot/src/main/java/cn/g3soft/utils/SnowflakeIdUtils.java index e4bc1e5f..45a9ded2 100644 --- a/code/base-project/base-springboot/src/main/java/cn/g3soft/utils/SnowflakeIdUtils.java +++ b/code/base-project/base-springboot/src/main/java/cn/g3soft/utils/SnowflakeIdUtils.java @@ -13,153 +13,85 @@ import java.util.concurrent.TimeUnit; @Slf4j public class SnowflakeIdUtils { - public static long MAX_START_INTERVAL_TIME = TimeUnit.SECONDS.toNanos(5L); - private static final long twepoch = 1288834974657L; + // 起始时间戳(建议设置为项目上线时间) + private static final long START_TIMESTAMP = 1288834974657L; - private static final long workerIdBits = 5L; - private static final long datacenterIdBits = 5L; - private static final long maxWorkerId = 31L; - private static final long maxDatacenterId = 31L; - private static final long sequenceBits = 12L; + // 各部分位数 + private static final long SEQUENCE_BITS = 12L; + private static final long MACHINE_BITS = 5L; + private static final long DATACENTER_BITS = 5L; - private static final long workerIdShift = 12L; - private static final long datacenterIdShift = 17L; - private static final long timestampLeftShift = 22L; - private static final long sequenceMask = 4095L; + // 最大值 + private static final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BITS); + private static final long MAX_MACHINE_ID = ~(-1L << MACHINE_BITS); + private static final long MAX_DATACENTER_ID = ~(-1L << DATACENTER_BITS); - // 这两个必须初始化 - private static long workerId; + // 左移位数 + private static final long MACHINE_LEFT = SEQUENCE_BITS; + private static final long DATACENTER_LEFT = SEQUENCE_BITS + MACHINE_BITS; + private static final long TIMESTAMP_LEFT = SEQUENCE_BITS + MACHINE_BITS + DATACENTER_BITS; + + // 参数及状态(静态) private static long datacenterId; - + private static long machineId; private static long sequence = 0L; private static long lastTimestamp = -1L; + private static boolean initialized = false; - private static InetAddress inetAddress; - - // 初始化一次即可,线程安全调用 - public static synchronized void init(InetAddress address) { - if (inetAddress == null) { - inetAddress = address; - datacenterId = getDatacenterId(maxDatacenterId); - workerId = getMaxWorkerId(datacenterId, maxWorkerId); - long start = System.nanoTime(); - long end = System.nanoTime(); - if (end - start > MAX_START_INTERVAL_TIME) { - log.warn("Initialization Sequence Very Slow! Get datacenterId:{} workerId:{}", datacenterId, workerId); - } else { - initLog(); - } + // 初始化方法(只能调用一次) + public static synchronized void init(long dcId, long mId) { + if (initialized) { + throw new IllegalStateException("SnowflakeIdGenerator has already been initialized."); } - } - - public static synchronized void init(long fixedWorkerId, long fixedDatacenterId) { - Assert.isTrue(fixedWorkerId <= maxWorkerId && fixedWorkerId >= 0, - String.format("worker Id can't be greater than %d or less than 0", maxWorkerId)); - Assert.isTrue(fixedDatacenterId <= maxDatacenterId && fixedDatacenterId >= 0, - String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId)); - workerId = fixedWorkerId; - datacenterId = fixedDatacenterId; - initLog(); - } - - private static void initLog() { - if (log.isDebugEnabled()) { - log.debug("Initialization Sequence datacenterId:{} workerId:{}", datacenterId, workerId); + if (dcId > MAX_DATACENTER_ID || dcId < 0) { + throw new IllegalArgumentException("datacenterId must be between 0 and " + MAX_DATACENTER_ID); } - } - - protected static long getMaxWorkerId(long datacenterId, long maxWorkerId) { - StringBuilder mpid = new StringBuilder(); - mpid.append(datacenterId); - String name = ManagementFactory.getRuntimeMXBean().getName(); - if (StringUtils.isNotBlank(name)) { - mpid.append(name.split("@")[0]); + if (mId > MAX_MACHINE_ID || mId < 0) { + throw new IllegalArgumentException("machineId must be between 0 and " + MAX_MACHINE_ID); } - return (mpid.toString().hashCode() & 0xffff) % (maxWorkerId + 1L); - } - - protected static long getDatacenterId(long maxDatacenterId) { - long id = 0L; - try { - if (inetAddress == null) { - if (log.isDebugEnabled()) { - log.debug("Use localhost address"); - } - inetAddress = InetAddress.getLocalHost(); - } - if (log.isDebugEnabled()) { - log.debug("Get {} network interface", inetAddress); - } - NetworkInterface network = NetworkInterface.getByInetAddress(inetAddress); - if (log.isDebugEnabled()) { - log.debug("Get network interface info: {}", network); - } - if (network == null) { - log.warn("Unable to get network interface for {}", inetAddress); - id = 1L; - } else { - byte[] mac = network.getHardwareAddress(); - if (mac != null && mac.length >= 2) { - id = ((0xffL & (long) mac[mac.length - 2]) | (0xff00L & ((long) mac[mac.length - 1] << 8))) >> 6; - id %= maxDatacenterId + 1L; - } - } - } catch (Exception e) { - log.warn("getDatacenterId error: {}", e.getMessage(), e); - } - return id; + datacenterId = dcId; + machineId = mId; + initialized = true; } + // 生成 ID(线程安全) public static synchronized long nextId() { - long timestamp = timeGen(); - - if (timestamp < lastTimestamp) { - long offset = lastTimestamp - timestamp; - if (offset > 5L) { - throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", offset)); - } - try { - SnowflakeIdUtils.class.wait(offset << 1); - timestamp = timeGen(); - if (timestamp < lastTimestamp) { - throw new RuntimeException(String.format("Clock moved backwards. Refusing to generate id for %d milliseconds", offset)); - } - } catch (InterruptedException e) { - throw new RuntimeException(e); - } + if (!initialized) { + throw new IllegalStateException("SnowflakeIdGenerator not initialized. Call init() first."); } - if (lastTimestamp == timestamp) { - sequence = (sequence + 1) & sequenceMask; + long currentTimestamp = timeGen(); + + if (currentTimestamp < lastTimestamp) { + throw new RuntimeException("Clock moved backwards. Refusing to generate id."); + } + + if (currentTimestamp == lastTimestamp) { + sequence = (sequence + 1) & MAX_SEQUENCE; if (sequence == 0) { - timestamp = tilNextMillis(lastTimestamp); + currentTimestamp = waitNextMillis(currentTimestamp); } } else { - sequence = ThreadLocalRandom.current().nextLong(1, 3); + sequence = 0L; } - lastTimestamp = timestamp; + lastTimestamp = currentTimestamp; - return ((timestamp - twepoch) << timestampLeftShift) - | (datacenterId << datacenterIdShift) - | (workerId << workerIdShift) + return ((currentTimestamp - START_TIMESTAMP) << TIMESTAMP_LEFT) + | (datacenterId << DATACENTER_LEFT) + | (machineId << MACHINE_LEFT) | sequence; } - protected static long tilNextMillis(long lastTimestamp) { - long timestamp = timeGen(); - while (timestamp <= lastTimestamp) { - timestamp = timeGen(); + private static long waitNextMillis(long currentTimestamp) { + while (currentTimestamp <= lastTimestamp) { + currentTimestamp = timeGen(); } - return timestamp; + return currentTimestamp; } - protected static long timeGen() { + private static long timeGen() { return System.currentTimeMillis(); } - - public static long parseIdTimestamp(long id) { - return (id >> 22) + 1288834974657L; - } } diff --git a/code/base-project/base-springboot/src/main/resources/datasource.yml b/code/base-project/base-springboot/src/main/resources/datasource.yml index cf88b4b7..2b9b0951 100644 --- a/code/base-project/base-springboot/src/main/resources/datasource.yml +++ b/code/base-project/base-springboot/src/main/resources/datasource.yml @@ -1,11 +1,22 @@ +#datasource: +# db1: +# url: jdbc:jtds:sqlserver://127.0.0.1:1433;databaseName=test1 +# username: sa +# password: sa +# driverClassName: net.sourceforge.jtds.jdbc.Driver +# db2: +# url: jdbc:jtds:sqlserver://127.0.0.1:1433;databaseName=test2 +# username: sa +# password: sa +# driverClassName: net.sourceforge.jtds.jdbc.Driver datasource: db1: - url: jdbc:jtds:sqlserver://127.0.0.1:1433;databaseName=test1 + url: jdbc:jtds:sqlserver://192.168.1.176:1433;databaseName=G3-Email username: sa password: sa driverClassName: net.sourceforge.jtds.jdbc.Driver db2: - url: jdbc:jtds:sqlserver://127.0.0.1:1433;databaseName=test2 + url: jdbc:jtds:sqlserver://192.168.1.176:1433;databaseName=G3-Website username: sa password: sa driverClassName: net.sourceforge.jtds.jdbc.Driver \ No newline at end of file