全局唯一id生成snowflake算法golang实现

2019-12-31  本文已影响0人  小怪兽狂殴奥特曼

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
上一篇 下一篇

猜你喜欢

热点阅读