本文目录导读:

我来详细介绍雪花算法的Java实现。
雪花算法结构
雪花算法的ID由64位二进制组成:
- 1位:符号位(始终为0)
- 41位:时间戳(毫秒级)
- 10位:工作机器ID
- 12位:序列号
基础实现
public class SnowflakeIdGenerator {
// 基础常量
private final long twepoch = 1609459200000L; // 2021-01-01 00:00:00
// 机器ID位数
private final long workerIdBits = 5L;
private final long datacenterIdBits = 5L;
// 序列号位数
private final long sequenceBits = 12L;
// 最大值计算
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
// 位移量
private final long workerIdShift = sequenceBits;
private final long datacenterIdShift = sequenceBits + workerIdBits;
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
// 组件值
private long workerId;
private long datacenterId;
private long sequence = 0L;
private long lastTimestamp = -1L;
public SnowflakeIdGenerator(long workerId, long datacenterId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(
String.format("Worker ID must be between 0 and %d", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(
String.format("Datacenter ID must be between 0 and %d", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}
public synchronized long nextId() {
long timestamp = timeGen();
// 时钟回拨处理
if (timestamp < lastTimestamp) {
long offset = lastTimestamp - timestamp;
if (offset <= 5) {
// 等待时间前进
try {
wait(offset * 100);
} catch (Exception e) {
Thread.yield();
}
timestamp = timeGen();
if (timestamp < lastTimestamp) {
throw new RuntimeException(
String.format("Clock moved backwards. Refusing for %d milliseconds", offset));
}
} else {
throw new RuntimeException(
String.format("Clock moved backwards. Refusing for %d milliseconds", offset));
}
}
// 同一毫秒内处理序列号
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0) {
// 序列号已满,等待下一毫秒
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
// 生成ID
return ((timestamp - twepoch) << timestampLeftShift)
| (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();
}
}
增强版实现(推荐)
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.util.Enumeration;
import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReentrantLock;
public class SnowflakeIdGeneratorV2 {
private final long twepoch = 1609459200000L;
private final long workerIdBits = 5L;
private final long datacenterIdBits = 5L;
private final long sequenceBits = 12L;
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
private final long workerIdShift = sequenceBits;
private final long datacenterIdShift = sequenceBits + workerIdBits;
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
private final long workerId;
private final long datacenterId;
private AtomicLong sequence = new AtomicLong(0);
private volatile long lastTimestamp = -1L;
private final ReentrantLock lock = new ReentrantLock();
// 自动获取机器ID
public SnowflakeIdGeneratorV2() {
this.datacenterId = getDatacenterId(maxDatacenterId);
this.workerId = getWorkerId(maxWorkerId, datacenterId);
}
public SnowflakeIdGeneratorV2(long workerId, long datacenterId) {
if (workerId > maxWorkerId || workerId < 0) {
throw new IllegalArgumentException(
String.format("Worker ID must be between 0 and %d", maxWorkerId));
}
if (datacenterId > maxDatacenterId || datacenterId < 0) {
throw new IllegalArgumentException(
String.format("Datacenter ID must be between 0 and %d", maxDatacenterId));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}
public long nextId() {
long timestamp = timeGen();
lock.lock();
try {
if (timestamp < lastTimestamp) {
// 处理时钟回拨
handleClockBackwards(lastTimestamp - timestamp);
timestamp = timeGen();
}
if (lastTimestamp == timestamp) {
long currentSequence = sequence.incrementAndGet() & sequenceMask;
if (currentSequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
sequence.set(currentSequence);
} else {
sequence.set(0L);
}
lastTimestamp = timestamp;
} finally {
lock.unlock();
}
return ((timestamp - twepoch) << timestampLeftShift)
| (datacenterId << datacenterIdShift)
| (workerId << workerIdShift)
| sequence.get();
}
private void handleClockBackwards(long offset) {
if (offset > 5) {
throw new RuntimeException(
String.format("Clock moved backwards. Refusing for %d milliseconds", offset));
}
try {
Thread.sleep(offset * 10);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new RuntimeException("Thread interrupted while waiting for clock recovery");
}
}
private long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
private long timeGen() {
return System.currentTimeMillis();
}
// 自动获取数据中心ID
private long getDatacenterId(long maxDatacenterId) {
long id = 0L;
try {
InetAddress ip = InetAddress.getLocalHost();
NetworkInterface network = NetworkInterface.getByInetAddress(ip);
if (network == null) {
id = 1L;
} else {
byte[] mac = network.getHardwareAddress();
if (null != mac) {
id = ((0x000000FF & (long) mac[mac.length - 1])
| (0x0000FF00 & (((long) mac[mac.length - 2]) << 8))) >> 6;
id = id % (maxDatacenterId + 1);
}
}
} catch (Exception e) {
id = 1L;
}
return id;
}
// 自动获取工作机器ID
private long getWorkerId(long maxWorkerId, long datacenterId) {
StringBuilder macString = new StringBuilder();
try {
Enumeration<NetworkInterface> interfaces = NetworkInterface.getNetworkInterfaces();
while (interfaces.hasMoreElements()) {
NetworkInterface networkInterface = interfaces.nextElement();
byte[] mac = networkInterface.getHardwareAddress();
if (mac != null) {
for (byte b : mac) {
macString.append(String.format("%02X", b));
}
break;
}
}
} catch (Exception e) {
// 使用默认值
}
return (macString.toString().hashCode() % (maxWorkerId + 1) + datacenterId) % (maxWorkerId + 1);
}
// 解析ID
public static Map<String, Long> parseId(long id) {
long sequence = id & 0xFFFL;
long workerId = (id >> 12) & 0x1FL;
long datacenterId = (id >> 17) & 0x1FL;
long timestamp = (id >> 22) + 1609459200000L;
Map<String, Long> result = new HashMap<>();
result.put("timestamp", timestamp);
result.put("datacenterId", datacenterId);
result.put("workerId", workerId);
result.put("sequence", sequence);
return result;
}
}
使用示例
public class SnowflakeIdDemo {
public static void main(String[] args) {
// 方式1:手动指定机器ID
SnowflakeIdGenerator generator1 = new SnowflakeIdGenerator(1L, 1L);
long id1 = generator1.nextId();
System.out.println("Generated ID: " + id1);
// 方式2:自动获取机器ID
SnowflakeIdGeneratorV2 generator2 = new SnowflakeIdGeneratorV2();
long id2 = generator2.nextId();
System.out.println("Generated ID: " + id2);
// 解析ID
Map<String, Long> parsed = SnowflakeIdGeneratorV2.parseId(id2);
System.out.println("Parsed ID: " + parsed);
// 批量生成测试
Set<Long> idSet = new HashSet<>(10000);
for (int i = 0; i < 10000; i++) {
long id = generator2.nextId();
if (!idSet.add(id)) {
System.out.println("Duplicate ID found: " + id);
}
}
System.out.println("Generated 10000 unique IDs successfully");
}
}
Spring Boot集成
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.beans.factory.annotation.Value;
@Configuration
public class SnowflakeConfig {
@Value("${snowflake.workerId:1}")
private long workerId;
@Value("${snowflake.datacenterId:1}")
private long datacenterId;
@Bean
public SnowflakeIdGeneratorV2 snowflakeIdGenerator() {
return new SnowflakeIdGeneratorV2(workerId, datacenterId);
}
}
// 使用示例
@Service
public class OrderService {
@Autowired
private SnowflakeIdGeneratorV2 snowflakeIdGenerator;
public Long createOrderId() {
return snowflakeIdGenerator.nextId();
}
}
高级特性实现
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.TimeUnit;
public class SnowflakeIdPool {
private final BlockingQueue<Long> idPool;
private final SnowflakeIdGeneratorV2 generator;
private volatile boolean running = true;
public SnowflakeIdPool(int poolSize, int workerId, int datacenterId) {
this.idPool = new LinkedBlockingQueue<>(poolSize);
this.generator = new SnowflakeIdGeneratorV2(workerId, datacenterId);
startIdProducer();
}
private void startIdProducer() {
Thread producer = new Thread(() -> {
while (running) {
try {
if (idPool.remainingCapacity() > 0) {
long id = generator.nextId();
idPool.offer(id);
}
Thread.sleep(1);
} catch (Exception e) {
Thread.currentThread().interrupt();
break;
}
}
}, "snowflake-id-producer");
producer.setDaemon(true);
producer.start();
}
public Long getId() {
try {
return idPool.poll(100, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
return generator.nextId();
}
}
public void shutdown() {
this.running = false;
}
}
关键设计要点
- 唯一性保证:时间戳+机器ID+序列号组合
- 高性能:使用位运算和原子操作
- 时钟回拨处理:等待或抛异常
- 线程安全:使用synchronized或Lock
配置建议
# application.yml snowflake: workerId: 1 datacenterId: 1
这个实现适合分布式系统,每秒可生成数百万个唯一ID。
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
足球直播
足球直播
足球直播
篮球直播
篮球直播
篮球直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
亚冠直播
亚冠直播
亚冠直播
欧冠直播
欧冠直播
欧冠直播
英超直播
英超直播
英超直播
西甲直播
西甲直播
西甲直播
中超直播
中超直播
中超直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
曼联直播
曼联直播
曼联直播
日职联直播
日职联直播
日职联直播
澳超直播
澳超直播
澳超直播
阿森纳直播
阿森纳直播
阿森纳直播
足球直播
足球直播
足球直播
NBA直播
NBA直播
NBA直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
欧冠直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
篮球直播
篮球直播
篮球直播
篮球直播
篮球直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播