Go实现雪花算法
一个简单的雪花算法的Go实现
需要的小伙伴直接拿去用就可以了。可以比较简单,一些数据你可以根据需要自定义就行了:
- 机器ID位数:没必要必须10位
- 开始时间戳:设置一个自己喜欢的,业务允许你只需要一天、一月的时间范围。42位也不是必须的。
- 序列所占位数,每msid范围,根据需要调整吧。
总得来说:除去第一个0是正负位不能变,其他63位,根据需要进行划分、组合,可以打进去很多信息,算法设计肯定很好,更多的希望你根据需要自我调整。
``
package main
import (
"fmt"
"sync"
"errors"
"time"
)
// 定义基本变量,雪花算法,时间戳,机器id,以及二者偏移量
const (
twepoch = int64(1483228800000) //开始时间戳(根据实际情况考虑)
workidBits = uint(4) // 机器id所占用位数
sequenceBits = uint(18) // 序列所占位数
workeridMax = int64(-1 ^ (-1 << workidBits)) //最大机器id
sequenceMask = int64(-1 ^ (-1 << sequenceBits)) //最大序列数
workIdShift = sequenceBits //机器id左移位数
timestampShift = sequenceBits + workidBits
)
//雪花算法所需要的结构
type SnowFlake struct {
sync.Mutex
timestamp int64
workerId int64
sequence int64
}
func NewSnowflake(workerid int64)(*SnowFlake , error) {
fmt.Println("初始化")
if workerid < 0 || workerid > workeridMax {
return nil , errors.New("worker id must be between 0 and 1023")
}
return &SnowFlake{
timestamp : 0 ,
workerId : workerid ,
sequence : 0 ,
}, nil
}
func (s *SnowFlake) Generate() int64 {
s.Lock()
now := time.Now().UnixNano()/1000000
//fmt.Println(now << timestampShift)
if s.timestamp == now {
s.sequence = (s.sequence + 1 ) & sequenceMask
if s.sequence == 0 {
for now <= s.timestamp {
now = time.Now().UnixNano() / 1000000
}
}
}else{
s.sequence = 0
}
s.timestamp = now
r := int64( (now - 0)<< timestampShift | (s.workerId << workIdShift) | (s.sequence) )
s.Unlock()
return r ;
}
func main() {
snow := SnowFlake{}
//snow2 , _ := NewSnowflake(0)
//fmt.Printf("%p\t%p\n" , &snow , &*snow2)
count := 100 * 100 * 100 * 100 // * 100
start := time.Now().UnixNano()/1000000
for i := 0; i < count; i++ {
id := snow.Generate()
if id > 0 {
continue
}
/*
id2 := snow2.Generate()
if id !=id2 {
// fmt.Println(id , id2 )
}
*/
}
end := time.Now().UnixNano()/1000000
takes := (int) (end - start )
fmt.Println("运行" , count , "时间" , end - start)
fmt.Println("运行速度" , (uint64)(count / takes) )
}