110 lines
3.4 KiB
Java
Raw Normal View History

2023-02-16 15:28:15 +08:00
package com.zhgd.xmgl.config;
/**
* 0000000000 0 - 0000000000 0000000000 0000000000 0 - 00 0000000000 - 0000000000
* 11位标识 - 31位时间戳 - 12位服务序列号 - 10位顺序位
*
* 1.生成ID缩短至16位
* 2.31位精确到秒时间戳可使用68年生成16位ID时保证使用60.5年
* 3.12位服务序列号可以支持部署4096个节点
* 4.10位顺序位每秒生成1024个ID
* <p>
* 16位极值 对应时间戳13653676962013-04-08 04:48:16 对应数据中心ID 对应顺序位
* 最大值9007199254740991 21474836472081-04-26 08:02:23 4095 1023
* 16位值1000000000000000 2384185792020-10-27 16:11:15 416 0
* 最小值 4195329 12013-04-08 04:48:17 1 1
* <p>
* 1111111111111111111111111111111 111111111111 1111111111
* 0001110001101011111101010010011 000110100000 0000000000
* 0000000000000000000000000000001 000000000001 0000000001
*
* @program: wisdomSite
* @description:
* @author: Mr.Peng
* @create: 2021-12-16 18:19
**/
public class IDGenerator {
/**
* 服务序列号
*/
private long serviceSequence = 1L;
/**
* 时间戳开始计时时间 2013-04-08 04:48:16
*/
private final long startTimestamp = 1365367696L;
/**
* 默认顺序位的初始值
*/
private long sequence = 1L;
/**
* 顺序位2进制长度
*/
private final long sequenceBits = 10L;
/**
* 服务序列号2进制长度
*/
private final long serviceSequenceBits = 12L;
/**
* 服务序列号右移位数
*/
private final long serviceSequenceShift = sequenceBits;
/**
* 时间戳右移位数
*/
private final long timestampShift = sequenceBits + serviceSequenceBits;
/**
* 生成序列的掩码(10位所对应的最大整数值)这里为1023 (0b1111111111=1023)
*/
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
private long lastTimestamp = -1L;
public IDGenerator(Long serviceSequence) {
this.serviceSequence = serviceSequence;
}
/**
* 生成唯一的趋势递增的id
*/
public synchronized long nextId() {
long timestamp = timeGen();
if (timestamp < lastTimestamp) {
System.err.printf("clock is moving backwards. Rejecting requests until %d.", lastTimestamp);
throw new RuntimeException(String.format(
"Clock moved backwards. Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
}
if (lastTimestamp == timestamp) {
sequence = (sequence + 1L) & sequenceMask;
if (sequence == 0L) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
return ((timestamp - startTimestamp) << timestampShift) | (serviceSequence << serviceSequenceShift) | sequence;
}
private long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
private long timeGen() {
return System.currentTimeMillis() / 1000L;
}
}