// 落雪算法 来源: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)<= 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() }