| |
使用Go语言实现雪花算法生成唯一ID
package main
import (
"fmt"
"sync"
"time"
)
const (
// 时间戳占用41位
timestampBits = 41
// 机器ID占用5位
workerIdBits = 5
// 序列号占用12位
sequenceBits = 12
// 最大机器ID
maxWorkerId = -1 ^ (-1 << workerIdBits)
// 最大序列号
maxSequence = -1 ^ (-1 << sequenceBits)
// 时间戳左移位数
timestampLeftShift = sequenceBits + workerIdBits
// 机器ID左移位数
workerIdLeftShift = sequenceBits
)
type Snowflake struct {
sync.Mutex
workerId int64
sequence int64
lastTimestamp int64
}
func NewSnowflake(workerId int64) (*Snowflake, error) {
if workerId < 0 || workerId > maxWorkerId {
return nil, fmt.Errorf("worker Id must be between 0 and %d", maxWorkerId)
}
return &Snowflake{
workerId: workerId,
lastTimestamp: -1,
}, nil
}
func (s *Snowflake) NextId() int64 {
s.Lock()
defer s.Unlock()
now := time.Now().UnixNano() / 1000000
if now == s.lastTimestamp {
s.sequence = (s.sequence + 1) & maxSequence
if s.sequence == 0 {
for now <= s.lastTimestamp {
now = time.Now().UnixNano() / 1000000
}
}
} else {
s.sequence = 0
}
s.lastTimestamp = now
id := ((now - 1420070400000) << timestampLeftShift) |
(s.workerId << workerIdLeftShift) |
s.sequence
return id
}
func main() {
snowflake, _ := NewSnowflake(1)
fmt.Println(snowflake.NextId())
}
该代码实现了雪花算法的核心逻辑,包括: