雪花算法
public class SnowflakeIdWorker {
private final long twepoch = 1420041600000L;
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 SnowflakeIdWorker(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) {
SnowflakeIdWorker idWorker = new SnowflakeIdWorker(0, 0);
for (int i = 0; i < 1000; i++) {
long id = idWorker.nextId();
System.out.println(id);
}
}
}
redis
public interface IdGeneratorService {
long generatorId(String biz);
long generatorId();
}
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import java.util.Calendar;
import java.util.Date;
@Service
@Slf4j
public class RedisIdGeneratorService implements IdGeneratorService {
private static final String KEY_PREFIX = "r_d";
private static final Jedis JEDIS;
static {
JEDIS = new Jedis("127.0.0.1", 6379);
}
private String getIdPrefix() {
Date date = new Date();
Calendar c = Calendar.getInstance();
c.setTime(date);
int year = c.get(Calendar.YEAR);
int day = c.get(Calendar.DAY_OF_YEAR);
int hour = c.get(Calendar.HOUR_OF_DAY);
int minute = c.get(Calendar.MINUTE);
int second = c.get(Calendar.SECOND);
String dayFmt = String.format("%1$03d", day);
String hourFmt = String.format("%1$02d", hour);
String minuteFmt = String.format("%1$02d", minute);
String secondFmt = String.format("%1$02d", second);
return (year - 2000) + dayFmt + hourFmt + minuteFmt + secondFmt;
}
private long incrDistrId(String biz) {
String prefix = getIdPrefix();
String orderId = null;
String key = "#{biz}:id:".replace("#{biz}", biz).concat(prefix);
try {
Long index = JEDIS.incrBy(key, 1);
orderId = prefix.concat(String.format("%1$05d", index));
} catch (Exception ex) {
log.error("分布式订单号生成失败异常。。。。。", ex);
} finally {
JEDIS.expire(key, 10 * 60);
}
if (isEmpty(orderId)) {
return 0;
}
return Long.parseLong(orderId);
}
private boolean isEmpty(String value) {
return null == value || value.length() == 0;
}
private boolean isNotEmpty(String value) {
return !isEmpty(value);
}
@Override
public long generatorId(String biz) {
return incrDistrId(biz);
}
@Override
public long generatorId() {
return incrDistrId(KEY_PREFIX);
}
public static void main(String[] args) {
IdGeneratorService idGeneratorService = new RedisIdGeneratorService();
for (int i = 0; i < 1000; i++) {
System.out.println(idGeneratorService.generatorId("key"));
}
}
}