package com.ideatech.ams.ucam.utils;
/**
* Created with IntelliJ IDEA.
* 用于生成唯一的数据库ID的工具类,基于雪花算法实现。
* <p>
* 雪花算法的特点:
* - 时间有序:生成的ID随时间递增,保证了ID的时序性。
* - 唯一性:在同一毫秒内生成的ID不会重复。
* - 分布式友好:适用于分布式系统,避免ID冲突。
* <p>
* 使用方式:
* 调用 generateUniqueId() 方法可以生成唯一的ID。
* <p>
* 注意事项:
* - 需要确保系统时钟不回退,以避免生成的ID不连续。
* - 在高并发情况下,需要测试生成的ID是否唯一。
*
* @author Gotham
* @date 2023/9/23 Time: 15:41
* Email: Gotham
*/
public class IdInitUtil {
private static final long EPOCH = 1632360000000L; // 设置一个起始时间戳(2021-09-24)
private static final long SEQUENCE_BITS = 12;
private static final long MAX_SEQUENCE = (1L << SEQUENCE_BITS) - 1;
private static final long SEQUENCE_SHIFT = 0;
private static final long TIMESTAMP_SHIFT = SEQUENCE_BITS;
private static final long MAX_SEQUENCE_NUMBER = 999L; // 每毫秒最多生成999个ID
private static long lastTimestamp = -1L;
private static long sequence = 0L;
/**
* 生成数据库唯一ID方法
*
* @return 唯一ID
* @throws RuntimeException 如果时钟回退或每毫秒生成的ID数量超过最大限制,将抛出异常
*/
public synchronized static long generateUniqueId() {
long currentTimestamp = System.currentTimeMillis();
if (currentTimestamp < lastTimestamp) {
throw new RuntimeException("时钟回退异常");
}
if (currentTimestamp == lastTimestamp) {
sequence = (sequence + 1) & MAX_SEQUENCE;
if (sequence == 0) {
// 当前毫秒内生成的ID超过最大限制
currentTimestamp = waitUntilNextMillis(currentTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = currentTimestamp;
long id = ((currentTimestamp - EPOCH) << TIMESTAMP_SHIFT) | (sequence << SEQUENCE_SHIFT);
if (sequence > MAX_SEQUENCE_NUMBER) {
throw new RuntimeException("每毫秒生成的ID数量超过最大限制");
}
return id;
}
/**
* 生成数据库唯一ID方法
*
* @return 唯一ID
* @throws RuntimeException 如果时钟回退或每毫秒生成的ID数量超过最大限制,将抛出异常
*/
public synchronized static long generateNumber() {
long currentTimestamp = System.currentTimeMillis();
if (currentTimestamp < lastTimestamp) {
throw new RuntimeException("时钟回退异常");
}
if (currentTimestamp == lastTimestamp) {
sequence = (sequence + 1) & MAX_SEQUENCE;
if (sequence == 0) {
// 当前毫秒内生成的ID超过最大限制
currentTimestamp = waitUntilNextMillis(currentTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = currentTimestamp;
long id = ((currentTimestamp - EPOCH) << TIMESTAMP_SHIFT) | (sequence << SEQUENCE_SHIFT);
if (sequence > MAX_SEQUENCE_NUMBER) {
throw new RuntimeException("每毫秒生成的ID数量超过最大限制");
}
return id;
}
/**
* 在同一毫秒内等待,直到下一个毫秒
*
* @param currentTimestamp 当前时间戳
* @return 下一个毫秒的时间戳
*/
private static long waitUntilNextMillis(long currentTimestamp) {
while (currentTimestamp <= lastTimestamp) {
currentTimestamp = System.currentTimeMillis();
}
return currentTimestamp;
}
}
06-28
621
“相关推荐”对你有帮助么?
-
非常没帮助
-
没帮助
-
一般
-
有帮助
-
非常有帮助
提交