雪花算法(Snowflake Algorithm)是一种用于生成全局唯一 ID 的算法,特别适用于分布式系统。它的设计目标是生成趋势递增、高性能、可扩展的唯一 ID。让我为您提供一个基于 Go 语言的雪花算法示例代码。
首先,我们需要定义一些常量,包括时间戳的位数、机器 ID 的位数和序列号的位数。这些常量将在后面的代码中使用到。以下是定义常量的代码示例:
const (
timestampBits = 41 // 时间戳位数
machineIDBits = 10 // 机器 ID 位数
sequenceBits = 12 // 序列号位数
maxMachineID = -1 ^ (-1 << machineIDBits) // 最大机器 ID
maxSequenceNum = -1 ^ (-1 << sequenceBits) // 最大序列号
)
接下来,我们定义一个结构体 Snowflake
,用于存储雪花算法生成 ID 所需的各个参数:
type Snowflake struct {
timestamp int64 // 时间戳
machineID int64 // 机器 ID
sequenceNum int64 // 序列号
}
然后,我们编写一个初始化方法,用来设置结构体中的初始值。时间戳字段可以使用当前时间戳,机器 ID 可根据实际需求设置,序列号初始值设为 0:
func NewSnowflake(machineID int64) *Snowflake {
if machineID < 0 || machineID > maxMachineID {
panic("Invalid machine ID")
}
return &Snowflake{
timestamp: time.Now().UnixNano() / 1e6,
machineID: machineID,
sequenceNum: 0,
}
}
最后,我们实现一个生成 ID 的方法,根据雪花算法的规则生成唯一 ID。具体实现过程包括获取当前时间戳、判断是否为同一毫秒、更新序列号等:
func (s *Snowflake) GenerateID() int64 {
currentTimestamp := time.Now().UnixNano() / 1e6
if currentTimestamp == s.timestamp {
s.sequenceNum = (s.sequenceNum + 1) & maxSequenceNum
if s.sequenceNum == 0 {
currentTimestamp = s.waitNextMillis()
}
} else {
s.sequenceNum = 0
}
s.timestamp = currentTimestamp
id := (currentTimestamp << (machineIDBits + sequenceBits)) | (s.machineID << sequenceBits) | s.sequenceNum
return id
}
func (s *Snowflake) waitNextMillis() int64 {
currentTimestamp := time.Now().UnixNano() / 1e6
for currentTimestamp <= s.timestamp {
currentTimestamp = time.Now().UnixNano() / 1e6
}
return currentTimestamp
}
您可以根据实际情况设置机器 ID,然后生成一些唯一 ID 并输出。以下是完整示例代码:
package main
import (
"fmt"
"time"
)
func main() {
machineID := 1 // 根据实际情况设置机器 ID
sf := NewSnowflake(int64(machineID))
// 生成10个唯一 ID 并输出
for i := 0; i < 10; i++ {
id := sf.GenerateID()
fmt.Println(id)
}
}