Java智慧分布式ID:雪花算法号段模式生成详解
在分布式系统中,为每个节点生成唯一且有序的ID是一个常见的需求。雪花算法(Snowflake Algorithm)是一种常用的分布式ID生成策略,它能够保证ID的唯一性、有序性和高效性。本文将围绕Java语言,详细介绍雪花算法的原理、实现以及号段模式生成。
一、雪花算法概述
雪花算法由Twitter开源,是一种基于时间戳的分布式ID生成算法。它将一个64位的长整型数字分为五个部分:
1. 时间戳(41位):表示从纪元(1970年1月1日)到当前时间的毫秒数。
2. 数据中心ID(5位):表示数据中心ID,用于区分不同数据中心。
3. 机器ID(5位):表示机器ID,用于区分同一数据中心内的不同机器。
4. 序列号(12位):表示同一毫秒内生成的ID序列号,用于保证同一毫秒内ID的有序性。
5. 机器ID左移(12位):用于生成机器ID,保证同一机器ID的有序性。
二、雪花算法实现
下面是使用Java实现雪花算法的示例代码:
java
public class SnowflakeIdWorker {
// 纪元时间戳(1970年1月1日)
private final long twepoch = 1288834974657L;
// 机器ID占用的位数
private final long workerIdBits = 5L;
// 数据中心ID占用的位数
private final long datacenterIdBits = 5L;
// 机器ID最大值
private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
// 数据中心ID最大值
private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
// 序列号占用的位数
private final long sequenceBits = 12L;
// 机器ID左移位数
private final long workerIdShift = sequenceBits;
// 数据中心ID左移位数
private final long datacenterIdShift = sequenceBits + workerIdBits;
// 时间戳左移位数
private final long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
// 序列号最大值
private final long sequenceMask = -1L ^ (-1L << sequenceBits);
// 上次生成ID的时间戳
private long lastTimestamp = -1L;
// 序列号
private long sequence = 0L;
// 数据中心ID
private long datacenterId;
// 机器ID
private long workerId;
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;
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();
}
}
三、号段模式生成
雪花算法生成的ID是全局唯一的,但有时我们还需要为特定业务生成有序的ID。这时,我们可以使用号段模式生成ID。
号段模式的核心思想是将ID空间划分为多个连续的号段,每个号段由一个起始ID和结束ID表示。当需要生成ID时,从对应的号段中取一个ID,并更新号段的起始ID。
下面是使用Java实现号段模式生成ID的示例代码:
java
public class SegmentIdGenerator {
private final long startId;
private final long endId;
private long currentId;
public SegmentIdGenerator(long startId, long endId) {
this.startId = startId;
this.endId = endId;
this.currentId = startId;
}
public synchronized long nextId() {
if (currentId > endId) {
throw new RuntimeException("No more id available");
}
return currentId++;
}
}
四、总结
本文详细介绍了Java智慧分布式ID:雪花算法号段模式生成的相关技术。雪花算法能够保证ID的唯一性、有序性和高效性,而号段模式则能够满足特定业务对有序ID的需求。在实际应用中,我们可以根据具体场景选择合适的ID生成策略。
Comments NOTHING