Go 语言 分布式 ID 生成 Snowflake 算法 Go 实现

Go阿木 发布于 2025-06-22 9 次阅读


Snowflake 算法 Go 语言实现:分布式 ID 生成解决方案

在分布式系统中,为每个实体生成唯一标识符(ID)是一个常见的需求。这种唯一标识符通常用于数据库主键、缓存键、消息队列的唯一标识等场景。Snowflake 算法是一种简单且高效的分布式 ID 生成方案,它能够保证 ID 的全局唯一性,并且具有高性能和可扩展性。

本文将介绍 Snowflake 算法的原理,并使用 Go 语言实现一个简单的 Snowflake ID 生成器。

Snowflake 算法原理

Snowflake 算法由 Twitter 的工程师设计,它将时间戳、数据中心 ID、机器 ID 和序列号组合成一个 64 位的整数。以下是 Snowflake 算法的组成部分:

1. 时间戳(41 位):使用毫秒级时间戳,41 位可以表示 2^41 毫秒,即 69 年。

2. 数据中心 ID(5 位):表示数据中心 ID,5 位可以表示 2^5 个数据中心。

3. 机器 ID(5 位):表示机器 ID,5 位可以表示 2^5 个机器。

4. 序列号(12 位):表示同一毫秒内生成的 ID 序列,12 位可以表示 2^12 个序列。

将这四部分组合起来,可以得到一个 64 位的 Snowflake ID。

Go 语言实现

下面是使用 Go 语言实现的 Snowflake ID 生成器:

go

package main

import (


"fmt"


"sync"


"time"


)

const (


timestampBits = 41


datacenterIdBits = 5


机器IdBits = 5


sequenceBits = 12

maxDatacenterId = 1 << datacenterIdBits


maxMachineId = 1 << 机器IdBits


maxSequence = 1 << sequenceBits

timeOffset = int64(time.Now().UnixMilli() - epoch)

datacenterId int64


机器Id int64


sequence int64


lastTimestamp int64


mu sync.Mutex


)

func init() {


// 初始化数据中心 ID 和机器 ID


datacenterId = 1


机器Id = 1


sequence = 0


lastTimestamp = -1


}

func genSnowflakeId() int64 {


mu.Lock()


defer mu.Unlock()

now := time.Now().UnixMilli()


if now < lastTimestamp {


panic("Clock moved backwards. Refusing to generate id.")


}

if lastTimestamp == now {


sequence = (sequence + 1) & maxSequence


if sequence == 0 {


now = tilNextMillis(lastTimestamp)


}


} else {


sequence = 0


}

lastTimestamp = now

id := ((now-int64(timeOffset))<<timestampBits) | (datacenterId<<datacenterIdBits) | (机器Id<<机器IdBits) | sequence


return id


}

func tilNextMillis(lastTimestamp int64) int64 {


t := time.Now().UnixMilli()


for t <= lastTimestamp {


t = time.Now().UnixMilli()


}


return t


}

func main() {


for i := 0; i < 10; i++ {


fmt.Println(genSnowflakeId())


}


}


代码解析

1. 定义常量:定义了时间戳、数据中心 ID、机器 ID 和序列号的位数,以及最大值。

2. 初始化:初始化数据中心 ID、机器 ID、序列号和最后的时间戳。

3. 生成 ID:获取当前时间戳,判断是否为同一毫秒,如果是则增加序列号,否则重置序列号并获取下一个时间戳。将时间戳、数据中心 ID、机器 ID 和序列号组合成 ID。

4. 等待下一个毫秒:如果当前时间戳小于最后的时间戳,则等待下一个毫秒。

总结

本文介绍了 Snowflake 算法的原理,并使用 Go 语言实现了一个简单的 Snowflake ID 生成器。通过这种方式,我们可以轻松地生成全局唯一的 ID,适用于分布式系统中的各种场景。在实际应用中,可以根据需求调整数据中心 ID、机器 ID 和序列号的位数,以满足不同的业务需求。