package com.mossle.core.id;
/*
1
0---0000000000 0000000000 0000000000 0000000000 0 --- 00000 ---00000 ---000000000000
在上面的字符串中,第一位为未使用(实际上也可作为long的符号位),接下来的41位为毫秒级时间,然后5位datacenter标识位,5位机器ID(并不算标识符,实际是为线程标识),然后12位该毫秒内的当前毫秒内的计数,加起来刚好64位,为一个Long型。
这样的好处是,整体上按照时间自增排序,并且整个分布式系统内不会产生ID碰撞(由datacenter和机器ID作区分),并且效率较高,经测试,snowflake每秒能够产生26万ID左右,完全满足需要。
*/
public class SnowFlakeIdGenerator implements IdGenerator {
private static final long workerIdBits = 4L;
public static final long maxWorkerId = -1L ^ (-1L << workerIdBits);
private static final long sequenceBits = 10L;
private static final long workerIdShift = sequenceBits;
private static final long timestampLeftShift = sequenceBits + workerIdBits;
public static final long sequenceMask = -1L ^ (-1L << sequenceBits);
// private static final long twepoch = 1361753741828L;
// (2016 - 1970) * 365 * 24 * 60 * 60 * 1000
// private long twepoch = 1450656000000L;
// 2016-2-14 11:08
private long twepoch = 1455419300740L;
private final long workerId;
private long sequence = 0L;
private long lastTimestamp = -1L;
public SnowFlakeIdGenerator(final long workerId) {
super();
if ((workerId > this.maxWorkerId) || (workerId < 0)) {
throw new IllegalArgumentException(String.format(
"worker Id can't be greater than %d or less than 0",
this.maxWorkerId));
}
this.workerId = workerId;
}
public Long generateId() {
return this.nextId();
}
public Long generateId(String name) {
return this.generateId();
}
public Long generateId(Class<?> clz) {
return this.generateId();
}
public synchronized long nextId() {
long timestamp = this.timeGen();
if (this.lastTimestamp == timestamp) {
this.sequence = (this.sequence + 1) & this.sequenceMask;
if (this.sequence == 0) {
System.out.println("###########" + sequenceMask);
timestamp = this.tilNextMillis(this.lastTimestamp);
}
} else {
this.sequence = 0;
}
if (timestamp < this.lastTimestamp) {
try {
throw new Exception(
String.format(
"Clock moved backwards. Refusing to generate id for %d milliseconds",
this.lastTimestamp - timestamp));
} catch (Exception e) {
e.printStackTrace();
}
}
this.lastTimestamp = timestamp;
long nextId = ((timestamp - twepoch) << timestampLeftShift)
| (this.workerId << this.workerIdShift) | (this.sequence);
// System.out.println("timestamp:" + timestamp + ",timestampLeftShift:"
// + timestampLeftShift + ",nextId:" + nextId + ",workerId:"
// + workerId + ",sequence:" + sequence);
return nextId;
}
private long tilNextMillis(final long lastTimestamp) {
long timestamp = this.timeGen();
while (timestamp <= lastTimestamp) {
timestamp = this.timeGen();
}
return timestamp;
}
private long timeGen() {
return System.currentTimeMillis();
}
public void setTwepoch(long twepoch) {
this.twepoch = twepoch;
}
public static void main(String[] args) {
SnowFlakeIdGenerator worker2 = new SnowFlakeIdGenerator(2);
System.out.println(worker2.nextId());
}
}