一、由来
雪花算法(Snowflake Algorithm)是一种用于生成分布式系统中唯一ID的算法。起初由Twitter设计,用于解决分布式系统中唯一ID的需求。这一算法的目标是生成全局唯一、有序的64位整数ID,以确保数据不冲突、不重复。
二、结构
雪花算法生成的ID由以下部分组成:
- 41位时间戳:精确到毫秒级,记录ID生成的时间。
- 10位机器ID:用于标识不同机器或节点,可自定义分配。
- 12位序列号:解决同一毫秒内生成多个ID的冲突问题。
三、工作原理
雪花算法的工作原理如下:
- 获取当前时间戳的41位,并将其左移22位,以获取时间戳部分。
- 获取机器ID,并将其左移12位,以获取机器ID部分。
- 生成序列号,同一毫秒内生成多个ID时,序列号递增。
- 合并时间戳、机器ID和序列号,形成64位整数ID。
四、应用场景与特点
雪花算法广泛应用于分布式系统,用于生成唯一标识符,如订单号、用户ID、消息ID等。在解决分布式系统中唯一ID生成需求时非常有效,已被众多大型互联网公司和开源项目采用。
主要有以下特点:
- 唯一性:雪花算法生成的ID在分布式环境下全局唯一,不会重复。
- 有序性:生成的ID有序,可根据ID大小排序。
- 高性能:ID生成速度快,适用于高并发的分布式系统。
- 可定制性:机器ID可自定义,适用于各种规模和需求的系统
五、Java代码实现
工具类:
代码语言:javascript复制package com.forum.core.Utils.Snowflake;
public class SnowflakeIdGenerator {
// ==============================字段==============================
private final long workerId; // 机器ID
private final long datacenterId; // 数据中心ID
private long sequence = 0L; // 序列号
// 配置参数
private static final long MAX_WORKER_ID = 31L;
private static final long MAX_DATACENTER_ID = 31L;
private static final long TIMESTAMP_BITS = 41L;
private static final long MAX_TIMESTAMP = ~(-1L << TIMESTAMP_BITS);
private static final long WORKER_ID_BITS = 5L;
private static final long DATACENTER_ID_BITS = 5L;
private static final long SEQUENCE_BITS = 12L;
// 位移偏移量
private static final long TIMESTAMP_SHIFT = SEQUENCE_BITS WORKER_ID_BITS DATACENTER_ID_BITS;
private static final long WORKER_ID_SHIFT = SEQUENCE_BITS DATACENTER_ID_BITS;
private static final long DATACENTER_ID_SHIFT = SEQUENCE_BITS;
private long lastTimestamp = -1L; // 上次生成ID的时间戳
// ==============================构造函数==============================
/**
* 构造函数
* @param workerId 机器ID (0 - 31)
* @param datacenterId 数据中心ID (0 - 31)
*/
public SnowflakeIdGenerator(long workerId, long datacenterId) {
// 检查workerId和datacenterId是否合法
if (workerId > MAX_WORKER_ID || workerId < 0) {
throw new IllegalArgumentException("Worker ID must be between 0 and " MAX_WORKER_ID);
}
if (datacenterId > MAX_DATACENTER_ID || datacenterId < 0) {
throw new IllegalArgumentException("Datacenter ID must be between 0 and " MAX_DATACENTER_ID);
}
// 设置workerId和datacenterId
this.workerId = workerId;
this.datacenterId = datacenterId;
}
// ==============================方法==============================
/**
* 生成唯一ID
* @return 唯一ID
*/
public synchronized long generateUniqueId() {
long timestamp = getCurrentTimestamp();
// 检查时钟回退情况
if (timestamp < lastTimestamp) {
throw new RuntimeException("Clock moved backwards. Refusing to generate ID.");
}
// 同一毫秒内自增序列号
if (timestamp == lastTimestamp) {
sequence = (sequence 1) & ((1 << SEQUENCE_BITS) - 1); // 自增并掩码
if (sequence == 0) {
// 序列号用完,等待下一毫秒
timestamp = getNextTimestamp(lastTimestamp);
}
} else {
sequence = 0L; // 不同毫秒重置序列号
}
lastTimestamp = timestamp;
// 组合生成唯一ID
return ((timestamp << TIMESTAMP_SHIFT) |
(datacenterId << DATACENTER_ID_SHIFT) |
(workerId << WORKER_ID_SHIFT) |
sequence);
}
/**
* 获取当前时间戳
* @return 当前时间戳(毫秒)
*/
private long getCurrentTimestamp() {
return System.currentTimeMillis();
}
/**
* 等待下一毫秒,直到获得新的时间戳
* @param lastTimestamp 上次生成ID的时间戳
* @return 新的时间戳
*/
private long getNextTimestamp(long lastTimestamp) {
long timestamp = getCurrentTimestamp();
while (timestamp <= lastTimestamp) {
timestamp = getCurrentTimestamp();
}
return timestamp;
}
// ==============================测试==============================
public static void main(String[] args) {
// 创建一个雪花算法生成器,传入机器ID和数据中心ID
SnowflakeIdGenerator idGenerator = new SnowflakeIdGenerator(0, 0);
// 生成10个唯一ID并打印
for (int i = 0; i < 10; i ) {
new Thread(()->{
long uniqueId = idGenerator.generateUniqueId();
System.out.println("Generated Unique ID: " uniqueId);
}).start();
}
}
}
测试输出:
代码语言:javascript复制Generated Unique ID: 7109423425210286080
Generated Unique ID: 7109423425214480385
Generated Unique ID: 7109423425214480384
Generated Unique ID: 7109423425210286081
Generated Unique ID: 7109423425214480389
Generated Unique ID: 7109423425214480388
Generated Unique ID: 7109423425214480387
Generated Unique ID: 7109423425214480386
Generated Unique ID: 7109423425214480391
Generated Unique ID: 7109423425214480390
六、总结
雪花算法是一种为分布式系统生成唯一ID的算法,具备唯一性、有序性和高性能等特点,适用于各类分布式系统。通过合理分配机器ID和序列号,满足不同规模和需求的系统,成为分布式系统中常用的ID生成方案。