package com.mz.common.core.utils.uuid;
import lombok.extern.slf4j.Slf4j;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.time.LocalDate;
import java.time.ZoneId;
@Slf4j
@SuppressWarnings("unused")
public class SnowFlake {
/**
* 开始时间, 2020-1-1. 时间戳位上并不存储实际的时间, 而是当前时间与开始时间的差值(秒)
*/
private final static long START_TIMESTAMP = LocalDate.of(2020, 1, 1)
.atStartOfDay(ZoneId.of("Z")).toEpochSecond();
/**
* ID结构: 32位时间戳(秒) + 10位机器 + 16位序列号
*/
private final static long TIMESTAMP_BIT = 32;
private final static long MACHINE_BIT = 10;
private final static long SEQUENCE_BIT = 16;
/**
* 最大机器号
*/
private final static long MAX_MACHINE = 1 << MACHINE_BIT - 1;
/**
* 最大序列号
*/
private static final long MAX_SEQUENCE = 1 << SEQUENCE_BIT - 1;
/**
* 机器位和时间戳左移位数.
*/
private final static long MACHINE_LEFT = SEQUENCE_BIT;
private final static long TIMESTAMP_LEFT = MACHINE_BIT + SEQUENCE_BIT;
/**
* 机器标识
*/
private static long machineId = 1;
private static boolean machineInitialized = false;
/**
* 序列号
*/
private static long sequence = 0L;
/**
* 上一次时间戳
*/
private static long lastTimestamp = -1L;
static {
initMachineId();
}
/**
* 获取分布式ID
*
* @return 分布式ID
*/
public static long nextId() {
return nextId(getNowSeconds());
}
private static synchronized long nextId(long nowSeconds) {
long currentTimestamp = nowSeconds;
// 当前时间异常, 自动校准
if (currentTimestamp < lastTimestamp) {
currentTimestamp = lastTimestamp;
}
// 相同秒内,序列号自增
if (currentTimestamp == lastTimestamp) {
long nextSequence = sequence + 1;
//同一秒的序列数已经达到最大, 获取下一秒的ID(直接使用下一秒)
if (nextSequence >= MAX_SEQUENCE) {
return nextId(nowSeconds + 1);
} else {
sequence = nextSequence;
}
} else {
// 不同秒内,序列号置重置为0, 重新计数
sequence = 0L;
}
lastTimestamp = currentTimestamp;
// 当前时间与开始时间的差值
long timeDelta = currentTimestamp - START_TIMESTAMP;
// 各段结构拼接("|"操作)成ID
return timeDelta << TIMESTAMP_LEFT
| machineId << MACHINE_LEFT
| sequence;
}
private static long getNowSeconds() {
return SystemClock.now() / 1000;
}
/**
* 通过hostname初始化机器ID, 将hostname各字符累加并对machineId最大值取余
* <p>虚拟主机: 可手工设置, eg:prod1 </p>
* <p>普通容器: 默认容器ID为HOSTNAME, eg: b88598ebca38</p>
* <p>K8s Pod: 默认Pod ID为HOSTNAME, eg: user-service-433cf-5f6d48c7f4-8fclh</p>
*/
private static void initMachineId() {
try {
if (!machineInitialized) {
String hostname = InetAddress.getLocalHost().getHostName();
char[] hostnameChars = hostname.toCharArray();
int sumOfHostname = 0;
for (char hostnameChar : hostnameChars) {
sumOfHostname += hostnameChar;
}
machineId = sumOfHostname % MAX_MACHINE;
log.info("====> Init machineId. hostname[" + hostname + "], machineId[" + machineId + "]");
}
} catch (UnknownHostException e) {
log.error("====> Init machineId failure");
e.printStackTrace();
} finally {
machineInitialized = true;
}
}
/**
* 覆盖默认machineID
*
* @param mid machineId
*/
public static void setMachineId(long mid) {
if (mid > 0) {
machineId = mid;
}
}
}
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
uuid.zip (3个子文件)
uuid
IdUtils.java 1KB
SnowFlake.java 4KB
SystemClock.java 3KB
共 3 条
- 1
资源评论
Paddy哥
- 粉丝: 18
- 资源: 4
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功