Snowflake算法核心
把时间戳,工作机器id,序列号组合在一起。

除了最高位bit标记为不可用以外,其余三组bit占位均可浮动,看具体的业务需求而定。
默认情况下41bit的时间戳可以支持该算法使用到2082年,10bit的工作机器id可以支持1023台机器,序列号支持1毫秒产生4095个自增序列id。
-
public class IdWorker {
-
-
private final long twepoch = 1288834974657L;
-
private final long workerIdBits = 5L;
-
private final long datacenterIdBits = 5L;
-
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
-
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
-
private final long sequenceBits = 12L;
-
private final long workerIdShift = sequenceBits;
-
private final long datacenterIdShift = sequenceBits + workerIdBits;
-
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
-
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
-
-
private long workerId;
-
private long datacenterId;
-
private long sequence = 0L;
-
private long lastTimestamp = -1L;
-
-
public IdWorker(long workerId, long datacenterId) {
-
if (workerId > maxWorkerId || workerId < 0) {
-
throw new IllegalArgumentException(
-
String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
-
}
-
if (datacenterId > maxDatacenterId || datacenterId < 0) {
-
throw new IllegalArgumentException(
-
String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
-
}
-
this.workerId = workerId;
-
this.datacenterId = datacenterId;
-
}
-
-
public synchronized long nextId() {
-
long timestamp = timeGen();
-
if (timestamp < lastTimestamp) {
-
throw new RuntimeException(String.format(
-
"Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
-
}
-
if (lastTimestamp == timestamp) {
-
sequence = (sequence + 1) & sequenceMask;
-
if (sequence == 0) {
-
timestamp = tilNextMillis(lastTimestamp);
-
}
-
} else {
-
sequence = 0L;
-
}
-
-
lastTimestamp = timestamp;
-
-
return ((timestamp - twepoch) << timestampLeftShift) | (datacenterId << datacenterIdShift)
-
| (workerId << workerIdShift) | sequence;
-
}
-
-
protected long tilNextMillis(long lastTimestamp) {
-
long timestamp = timeGen();
-
while (timestamp <= lastTimestamp) {
-
timestamp = timeGen();
-
}
-
return timestamp;
-
}
-
-
protected long timeGen() {
-
return System.currentTimeMillis();
-
}
-
-
public static void main(String[] args) {
-
IdWorker idWorker = new IdWorker(0, 0);
-
for (int i = 0; i < 1000; i++) {
-
long id = idWorker.nextId();
-
System.out.println(id);
-
}
-
}
-
}
原来设计的ID生成方式
http://blog.itpub.net/29254281/viewspace-1811711/
Snowflake有几个缺点
1.对于机器数量有限制
2.服务器时间一旦变更,比如回退时间.可能造成ID冲突
3.对于MySQL来说,应该还是我的那种方式Insert更快.但是没有具体验证.
参考:
http://www.lanindex.com/twitter-snowflake%EF%BC%8C64%E4%BD%8D%E8%87%AA%E5%A2%9Eid%E7%AE%97%E6%B3%95%E8%AF%A6%E8%A7%A3/
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29254281/viewspace-2118973/
,如需转载,请注明出处,否则将追究法律责任。