本文目录导读:

我将为您提供雪花算法的完整实现案例,包含多个语言的实现和详细说明。
Java 实现
public class SnowflakeIdGenerator {
// 各部分位数定义
private static final long SEQUENCE_BITS = 12L; // 序列号占12位
private static final long WORKER_ID_BITS = 5L; // 机器ID占5位
private static final long DATACENTER_ID_BITS = 5L; // 数据中心ID占5位
// 最大值计算
private static final long MAX_WORKER_ID = -1L ^ (-1L << WORKER_ID_BITS); // 最大机器ID
private static final long MAX_DATACENTER_ID = -1L ^ (-1L << DATACENTER_ID_BITS); // 最大数据中心ID
private static final long MAX_SEQUENCE = -1L ^ (-1L << SEQUENCE_BITS); // 最大序列号
// 位移量
private static final long WORKER_ID_SHIFT = SEQUENCE_BITS; // 机器ID左移位数
private static final long DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS; // 数据中心ID左移位数
private static final long TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS; // 时间戳左移位数
// 起始时间戳(2020-01-01,可自定义)
private static final long START_TIMESTAMP = 1577808000000L;
// 成员变量
private final long workerId; // 机器ID
private final long datacenterId; // 数据中心ID
private long sequence = 0L; // 序列号
private long lastTimestamp = -1L; // 上次生成ID的时间戳
/**
* 构造函数
*/
public SnowflakeIdGenerator(long workerId, long datacenterId) {
if (workerId > MAX_WORKER_ID || workerId < 0) {
throw new IllegalArgumentException(String.format("Worker ID 必须介于 0 和 %d 之间", MAX_WORKER_ID));
}
if (datacenterId > MAX_DATACENTER_ID || datacenterId < 0) {
throw new IllegalArgumentException(String.format("Datacenter ID 必须介于 0 和 %d 之间", MAX_DATACENTER_ID));
}
this.workerId = workerId;
this.datacenterId = datacenterId;
}
/**
* 生成下一个ID
*/
public synchronized long nextId() {
long timestamp = getCurrentTimestamp();
// 时间回退检查
if (timestamp < lastTimestamp) {
throw new RuntimeException(String.format("时钟回拨,拒绝生成ID,回拨时间:%d ms", lastTimestamp - timestamp));
}
// 同一毫秒内
if (lastTimestamp == timestamp) {
sequence = (sequence + 1) & MAX_SEQUENCE;
// 序列号用尽
if (sequence == 0) {
timestamp = getNextTimestamp(lastTimestamp);
}
} else {
// 不同毫秒,序列号重置
sequence = 0L;
}
lastTimestamp = timestamp;
// 组装ID
return ((timestamp - START_TIMESTAMP) << TIMESTAMP_SHIFT) |
(datacenterId << DATACENTER_ID_SHIFT) |
(workerId << WORKER_ID_SHIFT) |
sequence;
}
/**
* 获取当前时间戳
*/
private long getCurrentTimestamp() {
return System.currentTimeMillis();
}
/**
* 获取下一个时间戳
*/
private long getNextTimestamp(long lastTimestamp) {
long timestamp = getCurrentTimestamp();
while (timestamp <= lastTimestamp) {
timestamp = getCurrentTimestamp();
}
return timestamp;
}
// 解析ID(用于调试)
public static Map<String, Long> parseId(long id) {
Map<String, Long> result = new HashMap<>();
result.put("timestamp", (id >> TIMESTAMP_SHIFT) + START_TIMESTAMP);
result.put("datacenterId", (id >> DATACENTER_ID_SHIFT) & MAX_DATACENTER_ID);
result.put("workerId", (id >> WORKER_ID_SHIFT) & MAX_WORKER_ID);
result.put("sequence", id & MAX_SEQUENCE);
return result;
}
// 测试示例
public static void main(String[] args) {
SnowflakeIdGenerator generator = new SnowflakeIdGenerator(1, 1);
// 连续生成10个ID
for (int i = 0; i < 10; i++) {
long id = generator.nextId();
System.out.println("ID: " + id + " (长度: " + Long.toBinaryString(id).length() + "位)");
System.out.println("解析: " + parseId(id));
}
// 性能测试
long startTime = System.currentTimeMillis();
int testCount = 1000000;
for (int i = 0; i < testCount; i++) {
generator.nextId();
}
long endTime = System.currentTimeMillis();
System.out.println("\n生成 " + testCount + " 个ID耗时: " + (endTime - startTime) + " ms");
}
}
Python 实现
import time
import threading
class SnowflakeIdGenerator:
def __init__(self, worker_id, datacenter_id, start_timestamp=None):
# 定义位数
self.SEQUENCE_BITS = 12
self.WORKER_ID_BITS = 5
self.DATACENTER_ID_BITS = 5
# 计算最大值
self.MAX_WORKER_ID = -1 ^ (-1 << self.WORKER_ID_BITS)
self.MAX_DATACENTER_ID = -1 ^ (-1 << self.DATACENTER_ID_BITS)
self.MAX_SEQUENCE = -1 ^ (-1 << self.SEQUENCE_BITS)
# 位移量
self.WORKER_ID_SHIFT = self.SEQUENCE_BITS
self.DATACENTER_ID_SHIFT = self.SEQUENCE_BITS + self.WORKER_ID_BITS
self.TIMESTAMP_SHIFT = self.SEQUENCE_BITS + self.WORKER_ID_BITS + self.DATACENTER_ID_BITS
# 起始时间戳(默认2020-01-01)
self.START_TIMESTAMP = start_timestamp or 1577808000000
# 验证参数
if worker_id > self.MAX_WORKER_ID or worker_id < 0:
raise ValueError(f"worker_id 必须介于 0 和 {self.MAX_WORKER_ID} 之间")
if datacenter_id > self.MAX_DATACENTER_ID or datacenter_id < 0:
raise ValueError(f"datacenter_id 必须介于 0 和 {self.MAX_DATACENTER_ID} 之间")
# 初始化成员变量
self.worker_id = worker_id
self.datacenter_id = datacenter_id
self.sequence = 0
self.last_timestamp = -1
# 线程锁
self.lock = threading.Lock()
def _get_current_timestamp(self):
return int(time.time() * 1000)
def _get_next_timestamp(self, last_timestamp):
timestamp = self._get_current_timestamp()
while timestamp <= last_timestamp:
timestamp = self._get_current_timestamp()
return timestamp
def next_id(self):
with self.lock:
timestamp = self._get_current_timestamp()
# 时钟回拨检查
if timestamp < self.last_timestamp:
raise Exception(f"clock moved backwards. Refusing to generate id for {self.last_timestamp - timestamp} milliseconds")
# 同一毫秒内
if self.last_timestamp == timestamp:
self.sequence = (self.sequence + 1) & self.MAX_SEQUENCE
# 序列号用尽
if self.sequence == 0:
timestamp = self._get_next_timestamp(self.last_timestamp)
else:
# 新毫秒,序列号重置
self.sequence = 0
self.last_timestamp = timestamp
# 组装ID
return ((timestamp - self.START_TIMESTAMP) << self.TIMESTAMP_SHIFT) | \
(self.datacenter_id << self.DATACENTER_ID_SHIFT) | \
(self.worker_id << self.WORKER_ID_SHIFT) | \
self.sequence
def parse_id(self, snowflake_id):
"""解析ID的各个部分"""
result = {
'timestamp': (snowflake_id >> self.TIMESTAMP_SHIFT) + self.START_TIMESTAMP,
'datacenter_id': (snowflake_id >> self.DATACENTER_ID_SHIFT) & self.MAX_DATACENTER_ID,
'worker_id': (snowflake_id >> self.WORKER_ID_SHIFT) & self.MAX_WORKER_ID,
'sequence': snowflake_id & self.MAX_SEQUENCE
}
return result
# 使用示例
if __name__ == "__main__":
generator = SnowflakeIdGenerator(worker_id=1, datacenter_id=1)
print("=== 单线程测试 ===")
for i in range(5):
snowflake_id = generator.next_id()
print(f"ID: {snowflake_id}, 解析: {generator.parse_id(snowflake_id)}")
print("\n=== 多线程测试 ===")
import threading
def generate_ids():
for i in range(100):
snowflake_id = generator.next_id()
print(f"Thread {threading.current_thread().name}: {snowflake_id}")
threads = [threading.Thread(target=generate_ids) for _ in range(5)]
for t in threads:
t.start()
for t in threads:
t.join()
print(f"\n最终状态 - 最后时间戳: {generator.last_timestamp}, 序列号: {generator.sequence}")
Go 实现
package main
import (
"fmt"
"sync"
"time"
)
// SnowflakeIdConfig 配置
type SnowflakeIdConfig struct {
WorkerID int64
DatacenterID int64
StartTimestamp int64 // 可自定义起始时间戳
}
// SnowflakeIdGenerator 雪花算法生成器
type SnowflakeIdGenerator struct {
// 各部分位数
sequenceBits int64 // 序列号占12位
workerIDBits int64 // 机器ID占5位
datacenterIDBits int64 // 数据中心ID占5位
// 最大值
maxWorkerID int64
maxDatacenterID int64
maxSequence int64
// 位移量
workerIDShift int64
datacenterIDShift int64
timestampShift int64
// 起始时间戳(毫秒)
startTimestamp int64
// 状态
workerID int64
datacenterID int64
sequence int64
lastTimestamp int64
// 互斥锁
mutex sync.Mutex
}
// NewSnowflakeIdGenerator 创建生成器
func NewSnowflakeIdGenerator(config SnowflakeIdConfig) (*SnowflakeIdGenerator, error) {
generator := &SnowflakeIdGenerator{
sequenceBits: 12,
workerIDBits: 5,
datacenterIDBits: 5,
}
// 计算最大值
generator.maxWorkerID = -1 ^ (-1 << generator.workerIDBits)
generator.maxDatacenterID = -1 ^ (-1 << generator.datacenterIDBits)
generator.maxSequence = -1 ^ (-1 << generator.sequenceBits)
// 计算位移量
generator.workerIDShift = generator.sequenceBits
generator.datacenterIDShift = generator.sequenceBits + generator.workerIDBits
generator.timestampShift = generator.sequenceBits + generator.workerIDBits + generator.datacenterIDBits
// 设置起始时间戳(默认2020-01-01)
if config.StartTimestamp == 0 {
generator.startTimestamp = 1577808000000
} else {
generator.startTimestamp = config.StartTimestamp
}
// 验证参数
if config.WorkerID > generator.maxWorkerID || config.WorkerID < 0 {
return nil, fmt.Errorf("worker ID 必须介于 0 和 %d 之间", generator.maxWorkerID)
}
if config.DatacenterID > generator.maxDatacenterID || config.DatacenterID < 0 {
return nil, fmt.Errorf("datacenter ID 必须介于 0 和 %d 之间", generator.maxDatacenterID)
}
generator.workerID = config.WorkerID
generator.datacenterID = config.DatacenterID
generator.sequence = 0
generator.lastTimestamp = -1
return generator, nil
}
// getCurrentTimestamp 获取当前毫秒时间戳
func (g *SnowflakeIdGenerator) getCurrentTimestamp() int64 {
return time.Now().UnixNano() / int64(time.Millisecond)
}
// getNextTimestamp 获取下一个毫秒时间戳
func (g *SnowflakeIdGenerator) getNextTimestamp(lastTimestamp int64) int64 {
timestamp := g.getCurrentTimestamp()
for timestamp <= lastTimestamp {
timestamp = g.getCurrentTimestamp()
}
return timestamp
}
// NextID 生成下一个ID
func (g *SnowflakeIdGenerator) NextID() (int64, error) {
g.mutex.Lock()
defer g.mutex.Unlock()
timestamp := g.getCurrentTimestamp()
// 时钟回拨检查
if timestamp < g.lastTimestamp {
return 0, fmt.Errorf("时钟回拨,拒绝生成ID,回拨时间:%d ms", g.lastTimestamp-timestamp)
}
// 同一毫秒内
if g.lastTimestamp == timestamp {
g.sequence = (g.sequence + 1) & g.maxSequence
// 序列号用尽
if g.sequence == 0 {
timestamp = g.getNextTimestamp(g.lastTimestamp)
}
} else {
// 新毫秒,序列号重置
g.sequence = 0
}
g.lastTimestamp = timestamp
// 组装ID
return ((timestamp - g.startTimestamp) << g.timestampShift) |
(g.datacenterID << g.datacenterIDShift) |
(g.workerID << g.workerIDShift) |
g.sequence, nil
}
// ParseID 解析ID
func (g *SnowflakeIdGenerator) ParseID(id int64) map[string]int64 {
result := make(map[string]int64)
result["timestamp"] = (id >> g.timestampShift) + g.startTimestamp
result["datacenterID"] = (id >> g.datacenterIDShift) & g.maxDatacenterID
result["workerID"] = (id >> g.workerIDShift) & g.maxWorkerID
result["sequence"] = id & g.maxSequence
return result
}
func main() {
// 创建生成器
generator, err := NewSnowflakeIdGenerator(SnowflakeIdConfig{
WorkerID: 1,
DatacenterID: 1,
})
if err != nil {
fmt.Printf("创建生成器失败: %v\n", err)
return
}
// 单线程测试
fmt.Println("=== 单线程测试 ===")
for i := 0; i < 5; i++ {
id, _ := generator.NextID()
fmt.Printf("ID: %d, 解析: %v\n", id, generator.ParseID(id))
}
// 多线程测试
fmt.Println("\n=== 多线程测试 ===")
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func(threadNum int) {
defer wg.Done()
for j := 0; j < 100; j++ {
id, _ := generator.NextID()
fmt.Printf("线程 %d: %d\n", threadNum, id)
}
}(i)
}
wg.Wait()
// 性能测试
fmt.Println("\n=== 性能测试 ===")
start := time.Now()
const testCount = 1000000
for i := 0; i < testCount; i++ {
generator.NextID()
}
elapsed := time.Since(start)
fmt.Printf("生成 %d 个ID耗时: %v\n", testCount, elapsed)
}
Node.js (JavaScript) 实现
class SnowflakeIdGenerator {
constructor(workerId, datacenterId, startTimestamp = 1577808000000) {
// 定义位数
this.SEQUENCE_BITS = 12n;
this.WORKER_ID_BITS = 5n;
this.DATACENTER_ID_BITS = 5n;
// 计算最大值
this.MAX_WORKER_ID = -1n ^ (-1n << this.WORKER_ID_BITS);
this.MAX_DATACENTER_ID = -1n ^ (-1n << this.DATACENTER_ID_BITS);
this.MAX_SEQUENCE = -1n ^ (-1n << this.SEQUENCE_BITS);
// 位移量
this.WORKER_ID_SHIFT = this.SEQUENCE_BITS;
this.DATACENTER_ID_SHIFT = this.SEQUENCE_BITS + this.WORKER_ID_BITS;
this.TIMESTAMP_SHIFT = this.SEQUENCE_BITS + this.WORKER_ID_BITS + this.DATACENTER_ID_BITS;
// 起始时间戳
this.START_TIMESTAMP = BigInt(startTimestamp);
// 验证参数
if (workerId < 0n || workerId > this.MAX_WORKER_ID) {
throw new Error(`Worker ID 必须介于 0 和 ${this.MAX_WORKER_ID} 之间`);
}
if (datacenterId < 0n || datacenterId > this.MAX_DATACENTER_ID) {
throw new Error(`Datacenter ID 必须介于 0 和 ${this.MAX_DATACENTER_ID} 之间`);
}
// 初始化状态
this.workerId = BigInt(workerId);
this.datacenterId = BigInt(datacenterId);
this.sequence = 0n;
this.lastTimestamp = -1n;
}
getCurrentTimestamp() {
return BigInt(Date.now());
}
getNextTimestamp(lastTimestamp) {
let timestamp = this.getCurrentTimestamp();
while (timestamp <= lastTimestamp) {
timestamp = this.getCurrentTimestamp();
}
return timestamp;
}
nextId() {
let timestamp = this.getCurrentTimestamp();
// 时钟回拨检查
if (timestamp < this.lastTimestamp) {
throw new Error(`时钟回拨,拒绝生成ID,回拨时间:${this.lastTimestamp - timestamp} ms`);
}
// 同一毫秒内
if (this.lastTimestamp === timestamp) {
this.sequence = (this.sequence + 1n) & this.MAX_SEQUENCE;
// 序列号用尽
if (this.sequence === 0n) {
timestamp = this.getNextTimestamp(this.lastTimestamp);
}
} else {
// 新毫秒,序列号重置
this.sequence = 0n;
}
this.lastTimestamp = timestamp;
// 组装ID
return ((timestamp - this.START_TIMESTAMP) << this.TIMESTAMP_SHIFT) |
(this.datacenterId << this.DATACENTER_ID_SHIFT) |
(this.workerId << this.WORKER_ID_SHIFT) |
this.sequence;
}
parseId(id) {
return {
timestamp: Number((id >> this.TIMESTAMP_SHIFT) + this.START_TIMESTAMP),
datacenterId: Number((id >> this.DATACENTER_ID_SHIFT) & this.MAX_DATACENTER_ID),
workerId: Number((id >> this.WORKER_ID_SHIFT) & this.MAX_WORKER_ID),
sequence: Number(id & this.MAX_SEQUENCE)
};
}
}
// 使用示例
const generator = new SnowflakeIdGenerator(1n, 1n);
console.log("=== 测试生成ID ===");
for (let i = 0; i < 5; i++) {
const id = generator.nextId();
console.log(`ID: ${id.toString()}`);
console.log(`解析: ${JSON.stringify(generator.parseId(id))}`);
}
// 性能测试
console.log("\n=== 性能测试 ===");
const start = Date.now();
const count = 100000;
for (let i = 0; i < count; i++) {
generator.nextId();
}
const end = Date.now();
console.log(`生成 ${count} 个ID耗时: ${end - start} ms`);
C# 实现
using System;
using System.Collections.Generic;
using System.Threading;
public class SnowflakeIdGenerator
{
// 各部分位数
private const long SEQUENCE_BITS = 12L;
private const long WORKER_ID_BITS = 5L;
private const long DATACENTER_ID_BITS = 5L;
// 最大值
private const long MAX_WORKER_ID = -1L ^ (-1L << (int)WORKER_ID_BITS);
private const long MAX_DATACENTER_ID = -1L ^ (-1L << (int)DATACENTER_ID_BITS);
private const long MAX_SEQUENCE = -1L ^ (-1L << (int)SEQUENCE_BITS);
// 位移量
private const long WORKER_ID_SHIFT = SEQUENCE_BITS;
private const long DATACENTER_ID_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS;
private const long TIMESTAMP_SHIFT = SEQUENCE_BITS + WORKER_ID_BITS + DATACENTER_ID_BITS;
// 起始时间戳(2020-01-01)
private const long START_TIMESTAMP = 1577808000000L;
// 成员变量
private readonly long workerId;
private readonly long datacenterId;
private long sequence = 0L;
private long lastTimestamp = -1L;
private readonly object lockObject = new object();
public SnowflakeIdGenerator(long workerId, long datacenterId)
{
if (workerId > MAX_WORKER_ID || workerId < 0)
throw new ArgumentException($"Worker ID 必须介于 0 和 {MAX_WORKER_ID} 之间");
if (datacenterId > MAX_DATACENTER_ID || datacenterId < 0)
throw new ArgumentException($"Datacenter ID 必须介于 0 和 {MAX_DATACENTER_ID} 之间");
this.workerId = workerId;
this.datacenterId = datacenterId;
}
private long GetCurrentTimestamp()
{
return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
}
private long GetNextTimestamp(long lastTimestamp)
{
long timestamp = GetCurrentTimestamp();
while (timestamp <= lastTimestamp)
{
timestamp = GetCurrentTimestamp();
}
return timestamp;
}
public long NextId()
{
lock (lockObject)
{
long timestamp = GetCurrentTimestamp();
// 时钟回拨检查
if (timestamp < lastTimestamp)
{
throw new Exception($"时钟回拨,拒绝生成ID,回拨时间:{lastTimestamp - timestamp} ms");
}
// 同一毫秒内
if (lastTimestamp == timestamp)
{
sequence = (sequence + 1) & MAX_SEQUENCE;
// 序列号用尽
if (sequence == 0)
{
timestamp = GetNextTimestamp(lastTimestamp);
}
}
else
{
// 新毫秒,序列号重置
sequence = 0L;
}
lastTimestamp = timestamp;
// 组装ID
return ((timestamp - START_TIMESTAMP) << (int)TIMESTAMP_SHIFT) |
(datacenterId << (int)DATACENTER_ID_SHIFT) |
(workerId << (int)WORKER_ID_SHIFT) |
sequence;
}
}
public Dictionary<string, long> ParseId(long id)
{
var result = new Dictionary<string, long>
{
["timestamp"] = (id >> (int)TIMESTAMP_SHIFT) + START_TIMESTAMP,
["datacenterId"] = (id >> (int)DATACENTER_ID_SHIFT) & MAX_DATACENTER_ID,
["workerId"] = (id >> (int)WORKER_ID_SHIFT) & MAX_WORKER_ID,
["sequence"] = id & MAX_SEQUENCE
};
return result;
}
}
class Program
{
static void Main(string[] args)
{
var generator = new SnowflakeIdGenerator(1, 1);
Console.WriteLine("=== 测试生成ID ===");
for (int i = 0; i < 5; i++)
{
long id = generator.NextId();
Console.WriteLine($"ID: {id}");
Console.WriteLine($"解析: {string.Join(", ", generator.ParseId(id))}");
}
// 多线程测试
Console.WriteLine("\n=== 多线程测试 ===");
var threads = new List<Thread>();
for (int i = 0; i < 5; i++)
{
int threadNum = i;
var thread = new Thread(() =>
{
for (int j = 0; j < 100; j++)
{
long id = generator.NextId();
Console.WriteLine($"线程 {threadNum}: {id}");
}
});
threads.Add(thread);
thread.Start();
}
foreach (var thread in threads)
{
thread.Join();
}
// 性能测试
Console.WriteLine("\n=== 性能测试 ===");
var start = DateTime.Now;
const int count = 1000000;
for (int i = 0; i < count; i++)
{
generator.NextId();
}
var end = DateTime.Now;
Console.WriteLine($"生成 {count} 个ID耗时: {(end - start).TotalMilliseconds} ms");
}
}
核心要点说明
1 ID结构
| 符号位(1位) | 时间戳(41位) | 数据中心ID(5位) | 机器ID(5位) | 序列号(12位) |
0 自定义起始时间 0-31 0-31 0-4095
2 关键特性
- 时间戳:41位,可以支持69年的使用时间
- 数据中心ID:5位,支持32个数据中心
- 机器ID:5位,每个数据中心支持32台机器
- 序列号:12位,同一毫秒内支持4096个ID
3 注意事项
- 时钟回拨问题:需要处理系统时钟回拨的情况
- 线程安全:需要保证并发环境下的线程安全
- 位运算:使用位移和异或运算来组装ID
4 扩展优化
- 可以增加时钟回拨等待机制
- 可以支持自定义起始时间戳
- 可以调整位数分配以适应不同场景
选择合适的实现语言,根据实际业务需求调整参数即可使用。