分享
全局唯一id生成snowflake算法golang实现
小怪兽狂殴奥特曼 · · 1562 次点击 · · 开始浏览这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。
snowflake.go
package snowflake
import (
"fmt"
"time"
"errors"
)
/*
组成:0(1 bit) | timestamp in milli second (41 bit) | machine id (10 bit) | index (12 bit)
每毫秒最多生成4096个id,集群机器最多1024台
*/
type Snowflake struct {
lastTimestamp int64
index int16
machId int16
}
func (s *Snowflake)Init(id int16) error {
if id > 0xff {
return errors.New("illegal machine id")
}
s.machId = id
s.lastTimestamp = time.Now().UnixNano()/1e6
s.index = 0
return nil
}
func (s *Snowflake)GetId() (int64, error) {
curTimestamp := time.Now().UnixNano()/1e6
if (curTimestamp == s.lastTimestamp) {
s.index++
if(s.index>0xfff) {
s.index = 0xfff
return -1,errors.New("out of range")
}
} else {
//fmt.Printf("id/ms:%d -- %d\n", s.lastTimestamp, s.index)
s.index = 0
s.lastTimestamp = curTimestamp
}
return int64((0x1ffffffffff & s.lastTimestamp) << 22) + int64(0xff << 10) + int64(0xfff & s.index),nil
}
var UUID Snowflake
单元测试
snowflake_test.go
package snowflake
import (
"github.com/deckarep/golang-set"
"testing"
)
// 生成1亿个ID看有没有重复
func TestSnowFlake( t *testing.T ) {
UUID.Init(1024)
s := mapset.NewSet()
for i:=0;i<1e9;i++ {
id,err := UUID.GetId()
if err!= nil {
t.FailNow()
}
if(s.Add(id) == false) {
t.FailNow()
}
}
}
把代码都放到同一个文件夹下,运行
go test -v snowflake_test.go snowflake.go
有疑问加站长微信联系(非本文作者)
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
关注微信1562 次点击
添加一条新回复
(您需要 后才能回复 没有账号 ?)
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码` - 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传
收入到我管理的专栏 新建专栏
snowflake.go
package snowflake
import (
"fmt"
"time"
"errors"
)
/*
组成:0(1 bit) | timestamp in milli second (41 bit) | machine id (10 bit) | index (12 bit)
每毫秒最多生成4096个id,集群机器最多1024台
*/
type Snowflake struct {
lastTimestamp int64
index int16
machId int16
}
func (s *Snowflake)Init(id int16) error {
if id > 0xff {
return errors.New("illegal machine id")
}
s.machId = id
s.lastTimestamp = time.Now().UnixNano()/1e6
s.index = 0
return nil
}
func (s *Snowflake)GetId() (int64, error) {
curTimestamp := time.Now().UnixNano()/1e6
if (curTimestamp == s.lastTimestamp) {
s.index++
if(s.index>0xfff) {
s.index = 0xfff
return -1,errors.New("out of range")
}
} else {
//fmt.Printf("id/ms:%d -- %d\n", s.lastTimestamp, s.index)
s.index = 0
s.lastTimestamp = curTimestamp
}
return int64((0x1ffffffffff & s.lastTimestamp) << 22) + int64(0xff << 10) + int64(0xfff & s.index),nil
}
var UUID Snowflake
单元测试
snowflake_test.go
package snowflake
import (
"github.com/deckarep/golang-set"
"testing"
)
// 生成1亿个ID看有没有重复
func TestSnowFlake( t *testing.T ) {
UUID.Init(1024)
s := mapset.NewSet()
for i:=0;i<1e9;i++ {
id,err := UUID.GetId()
if err!= nil {
t.FailNow()
}
if(s.Add(id) == false) {
t.FailNow()
}
}
}
把代码都放到同一个文件夹下,运行
go test -v snowflake_test.go snowflake.go