123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378 |
- // 落雪算法 来源:Twitter snowflake
- // 实现目标:
- // 可以定义起始时间,节点ID位数,步长位数,时间单位
- // 避免所有对象都使用同一个序列,
- // 常规设置:1. 64位ID,最高位是符号位,不用,时间戳版本(41位时间戳, 69年),节点ID + 步长共22位,时间单位1MS
- // 时间单位1000ms(1s),(31时间,68年),节点ID + 步长共32位,
- // 修改时间: 20241128
- package snowflake
- import (
- "encoding/base64"
- "encoding/binary"
- "errors"
- "fmt"
- "strconv"
- "sync"
- "time"
- )
- // epochS: time in seconds,起始时间
- // nodeBits: the number of bits to use for node id, 节点ID位数,
- // stepBits: the number of bits to use for sequence number, 步长位数
- // node:节点ID
- const encodeBase32Map = "ybndrfg8ejkmcpqxot1uwisza345h769"
- var decodeBase32Map [256]byte
- const encodeBase58Map = "123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ"
- var decodeBase58Map [256]byte
- // A JSONSyntaxError is returned from UnmarshalJSON if an invalid ID is provided.
- type JSONSyntaxError struct{ original []byte }
- func (j JSONSyntaxError) Error() string {
- return fmt.Sprintf("invalid snowflake ID %q", string(j.original))
- }
- // ErrInvalidBase58 is returned by ParseBase58 when given an invalid []byte
- var ErrInvalidBase58 = errors.New("invalid base58")
- // ErrInvalidBase32 is returned by ParseBase32 when given an invalid []byte
- var ErrInvalidBase32 = errors.New("invalid base32")
- // Create maps for decoding Base58/Base32.
- // This speeds up the process tremendously.
- func init() {
- for i := 0; i < len(encodeBase58Map); i++ {
- decodeBase58Map[i] = 0xFF
- }
- for i := 0; i < len(encodeBase58Map); i++ {
- decodeBase58Map[encodeBase58Map[i]] = byte(i)
- }
- for i := 0; i < len(encodeBase32Map); i++ {
- decodeBase32Map[i] = 0xFF
- }
- for i := 0; i < len(encodeBase32Map); i++ {
- decodeBase32Map[encodeBase32Map[i]] = byte(i)
- }
- }
- // A Node struct holds the basic information needed for a snowflake generator
- // node
- type Node struct {
- mu sync.Mutex
- epoch time.Time
- time int64
- node int64
- step int64
- unitTime int64
- nodeMax int64
- // nodeMask int64
- stepMask int64
- timeMax int64
- timeShift uint8
- nodeShift uint8
- }
- // An ID is a custom type used for a snowflake ID. This is used so we can
- // attach methods onto the ID.
- type ID int64
- // NewNode returns a new snowflake node that can be used to generate snowflake
- // IDs
- func NewNode(node int64, nodeBits uint8, stepBits uint8, unitTime int64, epochS int64) (*Node, error) {
- if unitTime <= 0 {
- unitTime = 1
- }
- n := Node{}
- n.node = node
- n.nodeMax = -1 ^ (-1 << nodeBits)
- // n.nodeMask = n.nodeMax << stepBits
- n.stepMask = -1 ^ (-1 << stepBits)
- n.timeShift = nodeBits + stepBits
- n.nodeShift = stepBits
- n.unitTime = unitTime
- timeBits := 63 - n.timeShift
- n.timeMax = -1 ^ (-1 << timeBits)
- if n.node < 0 || n.node > n.nodeMax {
- return nil, errors.New("Node number must be between 0 and " + strconv.FormatInt(n.nodeMax, 10))
- }
- var curTime = time.Now()
- // add time.Duration to curTime to make sure we use the monotonic clock if available
- n.epoch = curTime.Add(time.Unix(epochS, 0).Sub(curTime))
- return &n, nil
- }
- // Generate creates and returns a unique snowflake ID
- // To help guarantee uniqueness
- // - Make sure your system is keeping accurate system time
- // - Make sure you never have multiple nodes running with the same node ID
- func (n *Node) Generate() ID {
- n.mu.Lock()
- now := (time.Since(n.epoch).Nanoseconds() / 1000000) / n.unitTime
- if now == n.time {
- n.step = (n.step + 1) & n.stepMask
- if n.step == 0 {
- for now <= n.time {
- now = (time.Since(n.epoch).Nanoseconds() / 1000000) / n.unitTime
- }
- }
- } else {
- n.step = 0
- }
- n.time = now
- r := ID((now)<<n.timeShift |
- (n.node << n.nodeShift) |
- (n.step),
- )
- n.mu.Unlock()
- return r
- }
- func (n *Node) RollGenerate() ID {
- n.mu.Lock()
- now := (time.Since(n.epoch).Nanoseconds() / 1000000) / n.unitTime
- if now == n.time {
- n.step = (n.step + 1) & n.stepMask
- if n.step == 0 {
- for now <= n.time {
- now = (time.Since(n.epoch).Nanoseconds() / 1000000) / n.unitTime
- }
- }
- } else {
- n.step = 0
- }
- n.time = now
- now2 := now & n.timeMax
- r := ID((now2)<<n.timeShift |
- (n.node << n.nodeShift) |
- (n.step),
- )
- n.mu.Unlock()
- return r
- }
- // Int64 returns an int64 of the snowflake ID
- func (f ID) Int64() int64 {
- return int64(f)
- }
- // String returns a string of the snowflake ID
- func (f ID) String() string {
- return strconv.FormatInt(int64(f), 10)
- }
- // ParseString converts a string into a snowflake ID
- func ParseString(id string) (ID, error) {
- i, err := strconv.ParseInt(id, 10, 64)
- return ID(i), err
- }
- // Base2 returns a string base2 of the snowflake ID
- func (f ID) Base2() string {
- return strconv.FormatInt(int64(f), 2)
- }
- // ParseBase2 converts a Base2 string into a snowflake ID
- func ParseBase2(id string) (ID, error) {
- i, err := strconv.ParseInt(id, 2, 64)
- return ID(i), err
- }
- // Base32 uses the z-base-32 character set but encodes and decodes similar
- // to base58, allowing it to create an even smaller result string.
- // NOTE: There are many different base32 implementations so becareful when
- // doing any interoperation.
- func (f ID) Base32() string {
- if f < 32 {
- return string(encodeBase32Map[f])
- }
- b := make([]byte, 0, 12)
- for f >= 32 {
- b = append(b, encodeBase32Map[f%32])
- f /= 32
- }
- b = append(b, encodeBase32Map[f])
- for x, y := 0, len(b)-1; x < y; x, y = x+1, y-1 {
- b[x], b[y] = b[y], b[x]
- }
- return string(b)
- }
- // ParseBase32 parses a base32 []byte into a snowflake ID
- // NOTE: There are many different base32 implementations so becareful when
- // doing any interoperation.
- func ParseBase32(b []byte) (ID, error) {
- var id int64
- for i := range b {
- if decodeBase32Map[b[i]] == 0xFF {
- return -1, ErrInvalidBase32
- }
- id = id*32 + int64(decodeBase32Map[b[i]])
- }
- return ID(id), nil
- }
- // Base36 returns a base36 string of the snowflake ID
- func (f ID) Base36() string {
- return strconv.FormatInt(int64(f), 36)
- }
- // ParseBase36 converts a Base36 string into a snowflake ID
- func ParseBase36(id string) (ID, error) {
- i, err := strconv.ParseInt(id, 36, 64)
- return ID(i), err
- }
- // Base58 returns a base58 string of the snowflake ID
- func (f ID) Base58() string {
- if f < 58 {
- return string(encodeBase58Map[f])
- }
- b := make([]byte, 0, 11)
- for f >= 58 {
- b = append(b, encodeBase58Map[f%58])
- f /= 58
- }
- b = append(b, encodeBase58Map[f])
- for x, y := 0, len(b)-1; x < y; x, y = x+1, y-1 {
- b[x], b[y] = b[y], b[x]
- }
- return string(b)
- }
- // ParseBase58 parses a base58 []byte into a snowflake ID
- func ParseBase58(b []byte) (ID, error) {
- var id int64
- for i := range b {
- if decodeBase58Map[b[i]] == 0xFF {
- return -1, ErrInvalidBase58
- }
- id = id*58 + int64(decodeBase58Map[b[i]])
- }
- return ID(id), nil
- }
- // Base64 returns a base64 string of the snowflake ID
- func (f ID) Base64() string {
- return base64.StdEncoding.EncodeToString(f.Bytes())
- }
- // ParseBase64 converts a base64 string into a snowflake ID
- func ParseBase64(id string) (ID, error) {
- b, err := base64.StdEncoding.DecodeString(id)
- if err != nil {
- return -1, err
- }
- return ParseBytes(b)
- }
- // Bytes returns a byte slice of the snowflake ID
- func (f ID) Bytes() []byte {
- return []byte(f.String())
- }
- // ParseBytes converts a byte slice into a snowflake ID
- func ParseBytes(id []byte) (ID, error) {
- i, err := strconv.ParseInt(string(id), 10, 64)
- return ID(i), err
- }
- // IntBytes returns an array of bytes of the snowflake ID, encoded as a
- // big endian integer.
- func (f ID) IntBytes() [8]byte {
- var b [8]byte
- binary.BigEndian.PutUint64(b[:], uint64(f))
- return b
- }
- // ParseIntBytes converts an array of bytes encoded as big endian integer as
- // a snowflake ID
- func ParseIntBytes(id [8]byte) ID {
- return ID(int64(binary.BigEndian.Uint64(id[:])))
- }
- // 时间41毫秒(69年), node+step=22
- func NewMsNode(node int64, nodeBits uint8) (*Node, error) {
- startTs := time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local)
- stepBits := uint8(22 - nodeBits)
- return NewNode(node, nodeBits, stepBits, 1, startTs.Unix())
- }
- // 时间41秒(68年), node+step=32
- func NewSecondNode(node int64, nodeBits uint8) (*Node, error) {
- startTs := time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local)
- stepBits := uint8(32 - nodeBits)
- return NewNode(node, nodeBits, stepBits, 1000, startTs.Unix())
- }
- // 时间毫秒30(298小时),node10(1023),步长23( 8388608 个)
- // 调用RollGenerate产生时间循环ID
- func NewTimeRoolNode(node int64, nodeBits uint8) (*Node, error) {
- startTs := time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local)
- stepBits := uint8(33 - nodeBits)
- return NewNode(node, nodeBits, stepBits, 1, startTs.Unix())
- }
- func testSnowflakeNode() {
- startTs := time.Date(2020, 1, 1, 0, 0, 0, 0, time.Local)
- seq, err := NewNode(0, 0, 22, 1, startTs.Unix())
- if err != nil {
- return
- }
- seq.Generate().Int64()
- seq2, err2 := NewNode(0, 0, 32, 1000, startTs.Unix())
- if err2 != nil {
- return
- }
- seq2.Generate().Int64()
- }
|