1.java自带uuid方式.
生成的uuid太长,且不为数字类型,不是自增长,影响数据查询效率
2.共享数据库生成id,N机器可以使用自增(1+N)...(N+N)
数据库压力大,维护成本高,需部署多台机器
3.使用Twitter的snowflake
snowflake,前42位为时间截(普通的13位long型时间,占长为41位),5位为datacenterId,5位为workerId,11位为sequenceId;(各自占长可以自行调节)
要求不同机器时间一致,否则id自增会发生问题
package com.quna.common.id.snowflake;
import java.util.Date;
import com.quna.common.id.IdGen;
public abstract class AbstractSnowflakeIdGen implements IdGen {
protected long lastTimestamp = -1;
protected long tilNextTimestamp() {
long nextTime = timestamp();
while (nextTime <= lastTimestamp) {
nextTime = timestamp();
}
return nextTime;
}
protected long timestamp() {
return System.currentTimeMillis();
}
protected abstract long timestampLeft();
public Date getDate(long nextId) {
long timestamp = (nextId >> timestampLeft());
return new Date(timestamp);
}
}
package com.quna.common.id.snowflake;
import com.quna.common.id.IdGen;
public class DatacenterSnowflakeIdGen extends AbstractSnowflakeIdGen implements IdGen{
private final long workerId;
private final long datacenterId;
private long sequence = 0;
private static final long datacenterBits = 5; //0~31
private static final long maxDatacenterId = -1L ^ (-1L << datacenterBits);
private static final long workerBits = 5; //0~31
private static final long maxWorkerId = -1L ^ (-1L << workerBits);
private static final long sequenceBits = 11; //0~2047;
private static final long sequenceMask = -1L ^ (-1L << sequenceBits);
private static final long timestampLeft = sequenceBits + workerBits + datacenterBits;//时间左移位置
private static final long datacenterIdLeft = sequenceBits + workerBits;//数据中心左移位置
private static final long workerIdLeft = sequenceBits;//工作id左移位置
public DatacenterSnowflakeIdGen(final int datacenterId,final int workerId) {
if (datacenterId < 0 || datacenterId > maxDatacenterId) {
throw new IllegalArgumentException(String.format("datacenterId can't be greater than %d and less than 0", maxDatacenterId));
}
if (workerId < 0 || workerId > maxWorkerId) {
throw new IllegalArgumentException(String.format("workerId can't be greater than %d and less than 0", maxWorkerId));
}
this.datacenterId = datacenterId;
this.workerId = workerId;
}
public synchronized long nextId() {
long ct = timestamp();
if (ct < lastTimestamp) {
throw new IllegalArgumentException("时间调整过,时间错乱");
}
if (ct == lastTimestamp) {
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
ct = tilNextTimestamp();
}
} else {
sequence = 0;
}
lastTimestamp = ct;
//System.out.println("timestamp:" + ct + ",timestampLeft:" + timestampLeft + ",workerId:" + workerId + ",sequence:" + sequence);
return (ct << timestampLeft) | (datacenterId << datacenterIdLeft) | (workerId << workerIdLeft) | sequence;
}
@Override
protected long timestampLeft() {
return timestampLeft;
}
}