本文目录导读:

我来为您提供Java实现雪花算法的完整案例:
标准雪花算法实现
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.HashSet;
import java.util.Set;
/**
* 雪花算法ID生成器
* 64位long类型:
* 1位符号位 + 41位时间戳 + 10位机器ID + 12位序列号
*/
public class SnowflakeIdGenerator {
// 基础常量
private static final long START_TIMESTAMP = 1700000000000L; // 起始时间戳,可自定义
// 各部分位数
private static final long SEQUENCE_BITS = 12L; // 序列号占用的位数
private static final long MACHINE_ID_BITS = 10L; // 机器ID占用的位数
// 最大值计算
private static final long MAX_SEQUENCE = ~(-1L << SEQUENCE_BITS); // 4095
private static final long MAX_MACHINE_ID = ~(-1L << MACHINE_ID_BITS); // 1023
// 位移量
private static final long MACHINE_ID_SHIFT = SEQUENCE_BITS; // 12
private static final long TIMESTAMP_SHIFT = SEQUENCE_BITS + MACHINE_ID_BITS; // 22
// 成员变量
private final long machineId; // 机器ID
private long sequence = 0L; // 序列号
private long lastTimestamp = -1L; // 上一次生成ID的时间戳
/**
* 构造函数
* @param machineId 机器ID (0-1023)
*/
public SnowflakeIdGenerator(long machineId) {
if (machineId < 0 || machineId > MAX_MACHINE_ID) {
throw new IllegalArgumentException(
String.format("机器ID必须在 0 到 %d 之间", MAX_MACHINE_ID)
);
}
this.machineId = machineId;
}
/**
* 生成下一个ID
*/
public synchronized long nextId() {
long currentTimestamp = System.currentTimeMillis();
if (currentTimestamp < lastTimestamp) {
// 处理时钟回拨问题
long offset = lastTimestamp - currentTimestamp;
if (offset <= 5) { // 容忍5ms的时钟回拨
try {
this.wait(offset << 1); // 等待2倍的时间
currentTimestamp = System.currentTimeMillis();
} catch (InterruptedException e) {
throw new RuntimeException("等待时钟前移异常", e);
}
if (currentTimestamp < lastTimestamp) {
throw new RuntimeException("时钟回拨过大,无法生成ID");
}
} else {
throw new RuntimeException("时钟回拨,当前时间戳异常");
}
}
if (currentTimestamp == lastTimestamp) {
// 同一毫秒内,序列号自增
sequence = (sequence + 1) & MAX_SEQUENCE;
if (sequence == 0) {
// 序列号用完,等待下一毫秒
currentTimestamp = getNextTimestamp(lastTimestamp);
}
} else {
// 不同毫秒,序列号重置
sequence = 0L;
}
lastTimestamp = currentTimestamp;
// 生成ID (时间戳左移22位 | 机器ID左移12位 | 序列号)
return ((currentTimestamp - START_TIMESTAMP) << TIMESTAMP_SHIFT)
| (machineId << MACHINE_ID_SHIFT)
| sequence;
}
/**
* 获取下一个毫秒时间戳
*/
private long getNextTimestamp(long lastTimestamp) {
long timestamp = System.currentTimeMillis();
while (timestamp <= lastTimestamp) {
timestamp = System.currentTimeMillis();
}
return timestamp;
}
/**
* 解析ID,返回各组成部分
*/
public IdParts parseId(long id) {
IdParts parts = new IdParts();
parts.timestamp = (id >> TIMESTAMP_SHIFT) + START_TIMESTAMP;
parts.machineId = (id >> MACHINE_ID_SHIFT) & MAX_MACHINE_ID;
parts.sequence = id & MAX_SEQUENCE;
return parts;
}
/**
* ID组成部分
*/
public static class IdParts {
public long timestamp;
public long machineId;
public long sequence;
@Override
public String toString() {
return String.format("时间戳: %d, 机器ID: %d, 序列号: %d",
timestamp, machineId, sequence);
}
}
// 测试方法
public static void main(String[] args) throws InterruptedException {
// 单线程测试
System.out.println("=== 单线程测试 ===");
SnowflakeIdGenerator generator = new SnowflakeIdGenerator(1);
for (int i = 0; i < 5; i++) {
long id = generator.nextId();
System.out.println("生成的ID: " + id);
System.out.println("二进制表示: " + Long.toBinaryString(id));
System.out.println("解析结果: " + generator.parseId(id));
System.out.println("------------------------");
}
// 多线程并发测试
System.out.println("\n=== 多线程并发测试 ===");
testConcurrency();
// 性能测试
System.out.println("\n=== 性能测试 ===");
testPerformance();
}
/**
* 并发测试
*/
private static void testConcurrency() throws InterruptedException {
final int threadCount = 10;
final int idCountPerThread = 1000;
ExecutorService executorService = Executors.newFixedThreadPool(threadCount);
Set<Long> ids = java.util.Collections.synchronizedSet(new HashSet<>());
CountDownLatch latch = new CountDownLatch(threadCount);
for (int i = 0; i < threadCount; i++) {
final int machineId = i % 1024;
executorService.submit(() -> {
SnowflakeIdGenerator generator = new SnowflakeIdGenerator(machineId);
for (int j = 0; j < idCountPerThread; j++) {
ids.add(generator.nextId());
}
latch.countDown();
});
}
latch.await();
executorService.shutdown();
int totalCount = threadCount * idCountPerThread;
long startTime = System.currentTimeMillis();
// 已经在上面的任务中生成,这里只是统计
System.out.println("生成的ID总数: " + totalCount);
System.out.println("唯一ID数量: " + ids.size());
System.out.println("重复ID数量: " + (totalCount - ids.size()));
}
/**
* 性能测试
*/
private static void testPerformance() {
int testCount = 1000000; // 100万个
SnowflakeIdGenerator generator = new SnowflakeIdGenerator(1);
long startTime = System.nanoTime();
for (int i = 0; i < testCount; i++) {
generator.nextId();
}
long endTime = System.nanoTime();
long durationMs = (endTime - startTime) / 1000000;
System.out.println("生成 " + testCount + " 个ID用时: " + durationMs + "ms");
System.out.println("每秒可生成: " + (testCount * 1000.0 / durationMs) + " 个ID");
}
}
分布式环境下的实现(简化版)
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.UUID;
/**
* 分布式环境雪花算法实现
* 支持分布式部署,自动获取机器ID
*/
public class DistributedSnowflakeIdGenerator {
// 配置常量
private static final long SEQUENCE_BITS = 12L;
private static final long DATA_CENTER_BITS = 5L; // 数据中心位数
private static final long WORKER_BITS = 5L; // 工作节点位数
private static final long SEQUENCE_MAX = ~(-1L << SEQUENCE_BITS);
private static final long DATA_CENTER_MAX = ~(-1L << DATA_CENTER_BITS);
private static final long WORKER_MAX = ~(-1L << WORKER_BITS);
private static final long WORKER_SHIFT = SEQUENCE_BITS;
private static final long DATA_CENTER_SHIFT = SEQUENCE_BITS + WORKER_BITS;
private static final long TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_BITS + DATA_CENTER_BITS;
private final long dataCenterId;
private final long workerId;
private long sequence = 0L;
private long lastTimestamp = -1L;
/**
* 构造函数
* @param dataCenterId 数据中心ID (0-31)
* @param workerId 工作节点ID (0-31)
*/
public DistributedSnowflakeIdGenerator(long dataCenterId, long workerId) {
if (dataCenterId > DATA_CENTER_MAX || dataCenterId < 0) {
throw new IllegalArgumentException("数据中心ID不能大于" + DATA_CENTER_MAX + "或小于0");
}
if (workerId > WORKER_MAX || workerId < 0) {
throw new IllegalArgumentException("工作节点ID不能大于" + WORKER_MAX + "或小于0");
}
this.dataCenterId = dataCenterId;
this.workerId = workerId;
}
/**
* 生成ID
*/
public synchronized long nextId() {
long timestamp = timeGen();
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format(
"时钟回拨,拒绝生成ID,回调了%d毫秒", lastTimestamp - timestamp
));
}
if (timestamp == lastTimestamp) {
sequence = (sequence + 1) & SEQUENCE_MAX;
if (sequence == 0) {
timestamp = tilNextMillis(lastTimestamp);
}
} else {
sequence = 0;
}
lastTimestamp = timestamp;
return ((timestamp - 1600000000000L) << TIMESTAMP_SHIFT)
| (dataCenterId << DATA_CENTER_SHIFT)
| (workerId << WORKER_SHIFT)
| sequence;
}
private long tilNextMillis(long lastTimestamp) {
long timestamp = timeGen();
while (timestamp <= lastTimestamp) {
timestamp = timeGen();
}
return timestamp;
}
private long timeGen() {
return System.currentTimeMillis();
}
/**
* 根据主机名获取工作节点ID
*/
private static long getWorkerIdByHostName() {
try {
String hostName = InetAddress.getLocalHost().getHostName();
long hash = hostName.hashCode();
return Math.abs(hash % 32);
} catch (UnknownHostException e) {
return (long) (UUID.randomUUID().getMostSignificantBits() % 32);
}
}
// 使用示例
public static void main(String[] args) {
// 创建分布式ID生成器
DistributedSnowflakeIdGenerator generator =
new DistributedSnowflakeIdGenerator(1, getWorkerIdByHostName());
// 生成并打印几个ID
for (int i = 0; i < 10; i++) {
System.out.println(generator.nextId());
}
}
}
使用示例和最佳实践
/**
* 雪花算法使用示例
*/
public class SnowflakeExample {
// 单例模式
private static class SingletonHolder {
private static final SnowflakeIdGenerator INSTANCE =
new SnowflakeIdGenerator(1); // 配置对应的机器ID
}
/**
* 获取全局唯一的ID生成器实例
*/
public static SnowflakeIdGenerator getInstance() {
return SingletonHolder.INSTANCE;
}
public static void main(String[] args) throws InterruptedException {
// 1. 基本使用
SnowflakeIdGenerator generator = getInstance();
Long id = generator.nextId();
System.out.println("生成的ID: " + id);
// 2. 批量生成
for (int i = 0; i < 5; i++) {
System.out.println("批量生成: " + generator.nextId());
}
// 3. 并发环境下使用
ExecutorService executor = Executors.newFixedThreadPool(10);
for (int i = 0; i < 100; i++) {
executor.execute(() -> {
Long orderId = generator.nextId();
System.out.println(Thread.currentThread().getName() + " 生成订单ID: " + orderId);
});
}
executor.shutdown();
// 4. 注意事项
System.out.println("\n=== 使用注意事项 ===");
System.out.println("1. 雪花算法生成的ID不是严格的递增,但是趋势递增");
System.out.println("2. 适用场景:分布式系统主键、订单号、消息ID等");
System.out.println("3. 需要配置好机器ID和数据中心ID");
System.out.println("4. 支持高并发,理论每秒可生成400万个ID");
System.out.println("5. 生成的ID是long类型的64位整数");
}
}
配置文件方式
import java.io.InputStream;
import java.util.Properties;
/**
* 配置文件方式创建雪花算法组件
*/
public class SnowflakeFactory {
/**
* 从配置文件加载配置并创建生成器
*/
public static SnowflakeIdGenerator createFromConfig(String configFile) throws Exception {
Properties props = new Properties();
try (InputStream input = SnowflakeFactory.class.getClassLoader()
.getResourceAsStream(configFile)) {
props.load(input);
}
long machineId = Long.parseLong(props.getProperty("machine.id", "1"));
return new SnowflakeIdGenerator(machineId);
}
}
// application.properties 配置文件示例:
/*
# 雪花算法配置
machine.id=1
# 起始时间戳(可选)
# epoch.timestamp=1700000000000
*/
扩展:Redis分布式ID生成器
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
/**
* 基于Redis实现分布式唯一ID
*/
public class RedisIdGenerator {
private static final String ID_KEY = "current:id";
private final JedisPool jedisPool;
public RedisIdGenerator(String host, int port) {
this.jedisPool = new JedisPool(host, port);
}
/**
* 生成ID
*/
public long nextId() {
try (Jedis jedis = jedisPool.getResource()) {
return jedis.incr(ID_KEY);
}
}
/**
* 批量生成ID(优化)
*/
public long[] nextIds(int count) {
try (Jedis jedis = jedisPool.getResource()) {
return jedis.incrBy(ID_KEY, count) > 0 ? null : null;
// 简化处理,实际应根据业务实现
}
}
}
使用要点
- 机器ID配置:每台机器必须使用唯一的机器ID,通常在0-1023之间
- 时钟同步:确保服务器时间同步,避免时钟回拨问题
- 线程安全:使用
synchronized确保线程安全 - 性能优化:单机每秒可生成数百万个ID
- 监控告警:监控时钟回拨情况,异常时及时告警
这个实现已经考虑了:
- 时钟回拨问题
- 并发安全
- 分布式部署
- 性能优化
- 可扩展性
您可以根据实际业务需求选择合适的实现方式。