golang雪花算法
时间: 2023-06-28 09:13:10 浏览: 160
基于GO语言雪花算法库
雪花算法是一种分布式唯一ID生成算法,它可以保证在分布式环境下生成唯一的ID。在Golang中,我们可以使用以下代码实现雪花算法:
```go
package main
import (
"errors"
"fmt"
"sync"
"time"
)
const (
// StartTime 是雪花算法开始时间戳,用于减小生成的ID长度
StartTime = 1577808000000 // 2020-01-01 00:00:00的时间戳,单位毫秒
// MachineIDBits 机器ID的位数
MachineIDBits = 10
// SequenceBits 序列号的位数
SequenceBits = 12
// MachineIDShift 机器ID的移位长度
MachineIDShift = SequenceBits
// TimestampShift 时间戳的移位长度
TimestampShift = SequenceBits + MachineIDBits
// MaxMachineID 最大机器ID
MaxMachineID = -1 ^ (-1 << MachineIDBits)
// MaxSequence 最大序列号
MaxSequence = -1 ^ (-1 << SequenceBits)
)
// Snowflake 是雪花算法生成的唯一ID结构体
type Snowflake struct {
machineID int64 // 机器ID
sequence int64 // 序列号
lastStamp int64 // 上次生成ID的时间戳
idLock sync.Mutex
}
// NewSnowflake 创建一个新的雪花算法实例
func NewSnowflake(machineID int64) (*Snowflake, error) {
if machineID < 0 || machineID > MaxMachineID {
return nil, errors.New("machine ID out of range")
}
return &Snowflake{
machineID: machineID,
}, nil
}
// Generate 生成一个新的唯一ID
func (s *Snowflake) Generate() int64 {
s.idLock.Lock()
defer s.idLock.Unlock()
// 获取当前时间戳
now := time.Now().UnixNano() / 1e6
// 如果当前时间小于上次生成ID的时间戳,说明系统时间被调整过,此时应该返回错误
if now < s.lastStamp {
panic(fmt.Sprintf("time is moving backwards, refusing to generate id for %d milliseconds", s.lastStamp-now))
}
// 如果当前时间与上次生成ID的时间戳相同,说明在同一毫秒内生成了多次ID,此时应将序列号+1
if now == s.lastStamp {
s.sequence = (s.sequence + 1) & MaxSequence
if s.sequence == 0 {
// 序列号已经达到最大值,等待下一毫秒
for now <= s.lastStamp {
now = time.Now().UnixNano() / 1e6
}
}
} else {
// 当前时间与上次生成ID的时间戳不同,说明已经进入下一毫秒,序列号重置为0
s.sequence = 0
}
// 保存当前时间戳,用于下一次生成ID时使用
s.lastStamp = now
// 生成ID
id := (now-StartTime)<<TimestampShift | (s.machineID << MachineIDShift) | s.sequence
return id
}
func main() {
// 创建一个新的雪花算法实例,机器ID为1
sf, err := NewSnowflake(1)
if err != nil {
panic(err)
}
// 生成10个唯一ID
for i := 0; i < 10; i++ {
id := sf.Generate()
fmt.Println(id)
}
}
```
在上面的代码中,我们首先定义了一些常量,包括开始时间、机器ID的位数、序列号的位数等。然后,我们定义了一个Snowflake结构体,用于保存生成ID时需要用到的一些参数,如机器ID、序列号、上次生成ID的时间戳等。接着,我们定义了NewSnowflake函数,用于创建一个新的雪花算法实例,并检查机器ID是否超出范围。最后,我们定义了Generate函数,用于生成一个新的唯一ID。在Generate函数中,我们首先获取当前时间戳,然后判断当前时间是否小于上次生成ID的时间戳,如果是,则说明系统时间被调整过,此时应该返回错误;如果当前时间与上次生成ID的时间戳相同,则说明在同一毫秒内生成了多次ID,此时应将序列号+1;如果当前时间与上次生成ID的时间戳不同,则说明已经进入下一毫秒,序列号重置为0。最后,我们将当前时间戳、机器ID、序列号组合成一个64位的唯一ID返回。
在main函数中,我们创建了一个新的雪花算法实例,并调用Generate函数生成了10个唯一ID。
阅读全文