本文目录导读:

我来为您提供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
- 监控告警:监控时钟回拨情况,异常时及时告警
这个实现已经考虑了:
- 时钟回拨问题
- 并发安全
- 分布式部署
- 性能优化
- 可扩展性
您可以根据实际业务需求选择合适的实现方式。
版权声明: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直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播