本文目录导读:

我来为你详细介绍Java中雪花算法的实现案例。
基础雪花算法实现
public class SnowflakeIdWorker {
// ============================== 核心参数 ==============================
/** 开始时间戳 (2020-01-01) */
private final long epoch = 1577836800000L;
/** 机器ID所占位数 */
private final long workerIdBits = 5L;
/** 数据中心ID所占位数 */
private final long dataCenterIdBits = 5L;
/** 序列号所占位数 */
private final long sequenceBits = 12L;
/** 机器ID最大值 (31) */
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
/** 数据中心ID最大值 (31) */
private final long maxDataCenterId = -1L ^ (-1L << dataCenterIdBits);
/** 机器ID左移位数 (12) */
private final long workerIdShift = sequenceBits;
/** 数据中心ID左移位数 (12+5=17) */
private final long dataCenterIdShift = sequenceBits + workerIdBits;
/** 时间戳左移位数 (12+5+5=22) */
private final long timestampShift = sequenceBits + workerIdBits + dataCenterIdBits;
/** 序列号掩码 (4095) */
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;
// 生成最终ID
return ((timestamp - epoch) << timestampShift) |
(dataCenterId << dataCenterIdShift) |
(workerId << workerIdShift) |
sequence;
}
private long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
private long timeGen() {
return System.currentTimeMillis();
}
}
高级版本(包含回拨处理)
public class AdvancedSnowflakeIdWorker {
// ============================== 配置参数 ==============================
private static final long SEQUENCE_BITS = 12L;
private static final long WORKER_ID_BITS = 5L;
private static final long DATA_CENTER_ID_BITS = 5L;
private static final long SEQUENCE_MASK = ~(-1L << SEQUENCE_BITS);
private static final long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);
private static final long MAX_DATA_CENTER_ID = ~(-1L << DATA_CENTER_ID_BITS);
private static final long WORKER_ID_SHIFT = SEQUENCE_BITS;
private static final long DATA_CENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
private static final long TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATA_CENTER_ID_BITS;
// ============================== 时间回拨容忍度(毫秒) ==============================
private static final long BACKWARD_TOLERANCE = 1000L;
private long dataCenterId;
private long workerId;
private volatile long sequence = 0L;
private volatile long lastTimestamp = -1L;
private final AtomicBoolean lock = new AtomicBoolean(false);
// ============================== 构造方法 ==============================
public AdvancedSnowflakeIdWorker(long dataCenterId, long workerId) {
if (dataCenterId > MAX_DATA_CENTER_ID || dataCenterId < 0) {
throw new IllegalArgumentException("数据中心ID超出范围");
}
if (workerId > MAX_WORKER_ID || workerId < 0) {
throw new IllegalArgumentException("工作机器ID超出范围");
}
this.dataCenterId = dataCenterId;
this.workerId = workerId;
}
// ============================== 核心方法 ==============================
public long nextId() {
long timestamp = currentTimeMillis();
// 时间回拨处理
if (timestamp < lastTimestamp) {
long offset = lastTimestamp - timestamp;
if (offset <= BACKWARD_TOLERANCE) {
// 小幅度回拨,等待时间追上
timestamp = waitForTime(lastTimestamp);
} else {
// 大幅度回拨,抛异常
throw new RuntimeException("系统时间回拨超过容忍度");
}
}
// CAS方式保证线程安全
while (true) {
if (lock.compareAndSet(false, true)) {
try {
if (timestamp == lastTimestamp) {
sequence = (sequence + 1) & SEQUENCE_MASK;
if (sequence == 0) {
timestamp = waitForNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
} finally {
lock.set(false);
}
break;
}
}
return generateId(timestamp);
}
private long generateId(long timestamp) {
return ((timestamp - getEpoch()) << TIMESTAMP_SHIFT) |
(dataCenterId << DATA_CENTER_ID_SHIFT) |
(workerId << WORKER_ID_SHIFT) |
sequence;
}
private long waitForTime(long lastTimestamp) {
long timestamp = currentTimeMillis();
while (timestamp < lastTimestamp) {
timestamp = currentTimeMillis();
}
return timestamp;
}
private long waitForNextMillis(long lastTimestamp) {
long timestamp = currentTimeMillis();
while (timestamp <= lastTimestamp) {
timestamp = currentTimeMillis();
}
return timestamp;
}
private long getEpoch() {
return 1577836800000L; // 2020-01-01 00:00:00
}
private long currentTimeMillis() {
return System.currentTimeMillis();
}
}
使用示例
public class SnowflakeDemo {
public static void main(String[] args) {
// 创建ID生成器
SnowflakeIdWorker idWorker = new SnowflakeIdWorker(1, 1);
AdvancedSnowflakeIdWorker advancedWorker = new AdvancedSnowflakeIdWorker(1, 1);
// 测试基础版本
System.out.println("===== 基础版本测试 =====");
for (int i = 0; i < 10; i++) {
long id = idWorker.nextId();
System.out.println("ID: " + id + " (长度: " + String.valueOf(id).length() + ")");
}
// 测试高级版本
System.out.println("\n===== 高级版本测试 =====");
for (int i = 0; i < 10; i++) {
long id = advancedWorker.nextId();
System.out.println("ID: " + id + " (长度: " + String.valueOf(id).length() + ")");
}
// 多线程测试
System.out.println("\n===== 多线程测试 =====");
testMultiThread(idWorker, 100);
}
private static void testMultiThread(SnowflakeIdWorker idWorker, int count) {
Set<Long> ids = new ConcurrentSkipListSet<>();
CountDownLatch latch = new CountDownLatch(count);
for (int i = 0; i < count; i++) {
new Thread(() -> {
try {
long id = idWorker.nextId();
ids.add(id);
} finally {
latch.countDown();
}
}).start();
}
try {
latch.await();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
System.out.println("生成ID数量: " + ids.size());
System.out.println("是否全部唯一: " + (ids.size() == count));
}
}
Spring Boot集成示例
@Component
public class SnowflakeIdGenerator {
@Value("${snowflake.worker-id:1}")
private long workerId;
@Value("${snowflake.datacenter-id:1}")
private long dataCenterId;
private SnowflakeIdWorker snowflakeIdWorker;
@PostConstruct
public void init() {
this.snowflakeIdWorker = new SnowflakeIdWorker(workerId, dataCenterId);
}
public long nextId() {
return snowflakeIdWorker.nextId();
}
public String nextIdStr() {
return String.valueOf(snowflakeIdWorker.nextId());
}
}
// 使用方式
@Service
public class UserService {
@Autowired
private SnowflakeIdGenerator idGenerator;
public User createUser(String name) {
User user = new User();
user.setId(idGenerator.nextId());
user.setName(name);
// ... 保存用户
return user;
}
}
自定义位数版本
public class CustomSnowflakeIdWorker {
private final long workerId;
private final long sequenceBits;
private final long sequenceMask;
private volatile long lastTimestamp = -1L;
private volatile long sequence = 0L;
public CustomSnowflakeIdWorker(long workerId, long sequenceBits) {
this.workerId = workerId;
this.sequenceBits = sequenceBits;
this.sequenceMask = -1L ^ (-1L << sequenceBits);
}
public synchronized long nextId() {
long timestamp = System.currentTimeMillis();
if (timestamp < lastTimestamp) {
throw new RuntimeException("时钟回拨");
}
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
return (timestamp << (63 - sequenceBits)) | (workerId << sequenceBits) | sequence;
}
private long tilNextMillis(long lastTimestamp) {
long timestamp = System.currentTimeMillis();
while (timestamp <= lastTimestamp) {
timestamp = System.currentTimeMillis();
}
return timestamp;
}
}
注意事项
- 唯一性保证:确保不同服务的
workerId和dataCenterId不重复 - 序列号溢出:单毫秒内生成的ID超过4095时,等待下一毫秒
- 时钟回拨:需要处理系统时间回拨的情况
- 线程安全:使用
synchronized或CAS保证线程安全 - 性能优化:预计算移位参数,减少运行时计算
这个实现已经在很多分布式系统中得到验证,性能优异,单机每秒可生成数百万个ID。