u
This commit is contained in:
1 parent
a4827cb646
commit
5c0ab2ce7d
3 files changed
+64
-122
No files matched your search
@@ -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);
|
||||
}
|
||||
}
|
||||
+51
-119
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
Reference in new issue
Block a user