本文目录导读:

我来详细讲解分布式ID雪花算法(Snowflake Algorithm)的原理和实现。
雪花算法简介
雪花算法是Twitter开源的分布式ID生成算法,用于在分布式系统中生成唯一的、有序的64位整数ID。
ID结构组成
1 bit | 41 bits | 10 bits | 12 bits
--------|-----------|-----------|-----------
符号位 | 时间戳 | 工作机器 | 序列号
(0) | (毫秒级) | ID | (自增)
各字段说明:
- 符号位(1bit):始终为0,保证ID为正数
- 时间戳(41bit):毫秒级时间戳,可使用69年
- 机器ID(10bit):支持1024台机器
- 序列号(12bit):同一毫秒内可生成4096个ID
核心代码实现
public class SnowflakeIdGenerator {
// 起始时间戳 (2021-01-01 00:00:00)
private final static long START_TIME = 1609459200000L;
// 各部分位数
private final static long WORKER_ID_BITS = 10L;
private final static long SEQUENCE_BITS = 12L;
// 最大值
private final static long MAX_WORKER_ID = ~(-1L << WORKER_ID_BITS);
private final static long MAX_SEQUENCE = ~(-1L << SEQUENCE_BITS);
// 左移位数
private final static long WORKER_ID_SHIFT = SEQUENCE_BITS;
private final static long TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
private long workerId;
private long sequence = 0L;
private long lastTimestamp = -1L;
public SnowflakeIdGenerator(long workerId) {
if (workerId > MAX_WORKER_ID || workerId < 0) {
throw new IllegalArgumentException(String.format(
"Worker ID must be between 0 and %d", MAX_WORKER_ID));
}
this.workerId = workerId;
}
// 生成下一个ID
public synchronized long nextId() {
long timestamp = System.currentTimeMillis();
// 时间回拨处理
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format(
"Clock moved backwards. Refusing to generate id for %d milliseconds",
lastTimestamp - timestamp));
}
// 同一毫秒内,序列号自增
if (timestamp == lastTimestamp) {
sequence = (sequence + 1) & MAX_SEQUENCE;
// 序列号用完,等待下一毫秒
if (sequence == 0) {
timestamp = waitNextMillis(timestamp);
}
} else {
// 不同毫秒,序列号重置
sequence = 0L;
}
lastTimestamp = timestamp;
// 组合各部分生成ID
return ((timestamp - START_TIME) << TIMESTAMP_SHIFT)
| (workerId << WORKER_ID_SHIFT)
| sequence;
}
// 等待下一毫秒
private long waitNextMillis(long currentTimestamp) {
long timestamp = System.currentTimeMillis();
while (timestamp <= currentTimestamp) {
timestamp = System.currentTimeMillis();
}
return timestamp;
}
}
性能优化版本
public class OptimizedSnowflakeIdGenerator {
private static final long START_TIME = 1609459200000L;
private static final long BITS_SEQUENCE = 12;
private static final long BITS_MACHINE = 10;
private static final long MASK_SEQUENCE = ~(-1L << BITS_SEQUENCE);
private static final long MAGIC_NUMBER = 1 << (BITS_MACHINE + BITS_SEQUENCE);
private final long machineId;
private volatile long lastTimestamp = -1L;
private volatile long sequence = 0L;
// 预置好的机器ID部分
private final long machineIdPart;
public OptimizedSnowflakeIdGenerator(long machineId) {
this.machineId = machineId;
this.machineIdPart = machineId << BITS_SEQUENCE;
}
public long nextId() {
long timestamp = System.currentTimeMillis();
// 处理时钟回拨
if (timestamp < lastTimestamp) {
long offset = lastTimestamp - timestamp;
if (offset <= 5) {
// 小范围回拨,等待
timestamp = waitUntil(timestamp);
} else {
throw new IllegalStateException("Clock moved backwards");
}
}
if (timestamp == lastTimestamp) {
sequence = (sequence + 1) & MASK_SEQUENCE;
if (sequence == 0) {
timestamp = waitUntil(timestamp);
}
} else {
sequence = 0L;
}
lastTimestamp = timestamp;
// 快速生成ID
return ((timestamp - START_TIME) * MAGIC_NUMBER)
+ machineIdPart
+ sequence;
}
private long waitUntil(long currentTimestamp) {
long timestamp = System.currentTimeMillis();
while (timestamp <= currentTimestamp) {
timestamp = System.currentTimeMillis();
}
return timestamp;
}
}
应用示例
public class SnowflakeDemo {
public static void main(String[] args) {
// 创建生成器(机器ID范围0-1023)
SnowflakeIdGenerator generator = new SnowflakeIdGenerator(1);
// 批量生成ID
for (int i = 0; i < 10; i++) {
long id = generator.nextId();
System.out.println("Generated ID: " + id);
}
// 测试性能
long startTime = System.currentTimeMillis();
int count = 1000000;
for (int i = 0; i < count; i++) {
generator.nextId();
}
long endTime = System.currentTimeMillis();
System.out.println("生成 " + count + " 个ID耗时: "
+ (endTime - startTime) + "ms");
System.out.println("每秒生成: " + (count * 1000 / (endTime - startTime)) + " 个");
}
}
优缺点分析
✅ 优点
- 全局唯一:分布式环境下保证ID唯一性
- 趋势递增:整体呈递增趋势,有利于数据库索引
- 高性能:纯内存计算,单机百万级/秒
- 业务含义:可反解析出生成时间、机器等信息
❌ 缺点
- 依赖机器时钟:时钟回拨可能导致ID重复
- 有限容量:单机每秒最多生成409.6万个(4096*1000)
改进方案
1 时钟回拨处理
// 方案1:等待时钟追上
private long handleClockBackwards(long lastTimestamp) {
long currentTimestamp = System.currentTimeMillis();
while (currentTimestamp < lastTimestamp) {
currentTimestamp = System.currentTimeMillis();
}
return currentTimestamp;
}
// 方案2:使用备用序列号
private long handleClockBackwardsWithBackup(long lastTimestamp, long sequence) {
if (sequence > 0) {
// 使用前一毫秒的序列号继续生成
this.sequence = (sequence + 1) & MAX_SEQUENCE;
return lastTimestamp;
}
// 等待时钟追上
return waitForClock(lastTimestamp);
}
2 扩展版本(百亿级ID)
public class ExtendedSnowflakeIdGenerator {
// 增加时间戳位数到51位
private static final long TIMESTAMP_BITS = 51L;
// 减少机器位和序列号位
private static final long WORKER_ID_BITS = 8L;
private static final long SEQUENCE_BITS = 4L;
// ... 实现逻辑类似,但支持更长时间
}
最佳实践
- 机器ID管理:通过Zookeeper或Redis统一分配
- 时钟同步:使用NTP服务同步时钟,避免大幅回拨
- 高可用部署:多个ID生成节点,通过负载均衡使用
雪花算法是分布式系统中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直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播
中超直播