snowflake

package
v0.0.16 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 28, 2026 License: MIT Imports: 7 Imported by: 0

README

snowflake

简介

snowflake 包实现了经典的 Snowflake 分布式唯一 ID 生成算法,适用于高并发、分布式系统中的唯一标识需求。该包支持多节点部署,生成的 64 位整数 ID 具备全局唯一性、趋势递增、可多种编码表示,广泛应用于数据库主键、分布式事务、消息队列等场景。

主要特性
  • 分布式唯一 ID 生成,支持多节点高并发
  • 生成 64 位整型 ID,趋势递增,适合排序
  • 支持多种编码格式(十进制、二进制、Base32、Base36、Base58、Base64)
  • 提供多种解析与转换方法,兼容多系统
  • 并发安全,适合高并发场景
  • 支持 JSON 序列化与反序列化
  • 完善的错误处理与边界校验
  • 单元测试覆盖率高
设计理念

snowflake 包遵循"高性能、易用性、兼容性"原则,采用互斥锁保证并发安全,节点号与序列号灵活配置,API 设计简洁直观。所有编码/解析方法均支持互逆,便于跨系统数据交换。

ID 结构说明

该库的 ID 由 64 位的整数组成,其中:

+---------------------------------------------------------------+
|  1 bit  |    41 bits    |  10 bits  |   12 bits   |
+---------------------------------------------------------------+
|  符号位 |  时间戳 (ms)  |  机器 ID  |  序列号    |
+---------------------------------------------------------------+

字段解释:

  • 1 bit:符号位(始终为 0)。
  • 41 bits:毫秒级时间戳(支持约 69 年)。
  • 10 bits:节点 ID(最多支持 1024 台机器)。
  • 12 bits:每毫秒最多生成 4096 个 ID。

安装

前置条件
  • Go 版本要求:Go 1.16+
  • 依赖要求:无外部依赖,仅用标准库
安装命令
go get -u github.com/fsyyft-go/kit/algorithms/snowflake

快速开始

基础用法
package main

import (
    "fmt"
    "github.com/fsyyft-go/kit/algorithms/snowflake"
)

func main() {
    // 创建节点(节点编号需唯一,范围 0~1023)
    node, err := snowflake.NewNode(1)
    if err != nil {
        panic(err)
    }
    // 生成唯一 ID
    id := node.Generate()
    fmt.Println("ID:", id.Int64())
    fmt.Println("Base58:", id.Base58())
}

详细指南

核心概念
  • ID 结构:64 位整数,由时间戳、节点编号、序列号组成,趋势递增。
  • 节点编号:每个节点需分配唯一编号,最大支持 1024 个节点(可配置)。
  • 序列号:同一毫秒内自增,避免并发冲突。
  • 多种编码:支持十进制、二进制、Base32、Base36、Base58、Base64 等多种编码与解析。
常见用例
1. 生成唯一 ID 并多种编码
id := node.Generate()
fmt.Println("十进制:", id.String())
fmt.Println("Base32:", id.Base32())
fmt.Println("Base58:", id.Base58())
fmt.Println("Base64:", id.Base64())
2. ID 解析与互逆
id := node.Generate()
s := id.Base58()
parsed, err := snowflake.ParseBase58([]byte(s))
if err != nil {
    // 处理解析错误
}
fmt.Println(parsed == id) // true
3. JSON 序列化与反序列化
import "encoding/json"

id := node.Generate()
b, _ := json.Marshal(id)
var id2 snowflake.ID
_ = json.Unmarshal(b, &id2)
fmt.Println(id == id2) // true
最佳实践
  • 每个节点分配唯一编号,避免冲突
  • 系统时间需准确,避免回拨
  • 并发场景下可安全调用 Generate
  • 合理选择编码格式,跨系统建议用十进制或 Base58
  • 检查解析函数返回的错误,防止非法输入

API 文档

主要类型
// Node 接口定义唯一 ID 生成方法
 type Node interface {
     Generate() ID
 }

// node 结构体实现 Node 接口
// ID 类型为 int64
关键函数
NewNode

创建新节点。

func NewNode(nodeid int64) (Node, error)
  • nodeid:节点编号,需唯一且在合法范围内
  • 返回 node 实例和错误
Generate

生成唯一 ID。

func (n *node) Generate() ID
ID 编码与解析
  • String():十进制字符串
  • Base2():二进制字符串
  • Base32():z-base-32 编码
  • Base36():base36 编码
  • Base58():base58 编码
  • Base64():base64 编码
  • Bytes():十进制字节切片
  • IntBytes():大端字节数组
解析函数
  • ParseString(s string) (ID, error)
  • ParseBase2(s string) (ID, error)
  • ParseBase32(b []byte) (ID, error)
  • ParseBase36(s string) (ID, error)
  • ParseBase58(b []byte) (ID, error)
  • ParseBase64(s string) (ID, error)
  • ParseBytes(b []byte) (ID, error)
  • ParseIntBytes([8]byte) ID
JSON 支持
  • MarshalJSON() ([]byte, error)
  • UnmarshalJSON([]byte) error
错误处理
  • 节点编号非法、编码解析失败等均返回详细错误
  • JSON 反序列化非法时返回自定义错误类型
  • 建议始终检查解析和创建节点的错误返回值

性能指标

操作 性能 说明
ID 生成 O(1) 支持高并发
编码/解析 O(n) n 为字符串长度

测试覆盖率

覆盖率
snowflake >95%

所有核心功能、边界和异常场景均有单元测试覆盖。

调试指南

常见问题排查
ID 重复
  • 检查节点编号是否唯一
  • 检查系统时间是否回拨
解析失败
  • 检查输入编码格式是否正确
  • 检查是否有非法字符

相关文档

贡献指南

欢迎任何形式的贡献,包括但不限于:

  • 报告问题
  • 提交功能建议
  • 提交代码改进
  • 完善文档

请参考贡献指南了解详细信息。

许可证

本项目采用 MIT License 许可证。查看 LICENSE 文件了解更多信息。

Documentation

Overview

Package snowflake 提供基于 Snowflake 位布局的分布式唯一 ID 生成能力。

NewNode 使用当前的 Epoch、NodeBits 和 StepBits 创建生成节点。调用方需要为每个 节点分配唯一的 nodeid,并在调整 Epoch 或位宽配置后重新创建节点,确保生成与解析 使用同一组位布局。

生成的 ID 支持十进制、Base2、z-base-32、Base36、Base58、Base64 以及字节表示, 并可通过对应的 Parse* 函数恢复。Time、Node 和 Step 等字段提取方法保留用于兼容旧 版本,它们依赖当前的全局位宽配置。

Index

Constants

This section is empty.

Variables

View Source
var (
	// Epoch 表示 Snowflake 算法的起始时间戳,单位为毫秒。
	// 默认值为项目约定的毫秒时间戳 1740515125000。
	// 调用方如需自定义,应在调用 NewNode 创建节点前完成配置。
	Epoch int64 = 1740515125000

	// NodeBits 表示节点编号占用的比特数。
	// NodeBits 和 StepBits 总和不能超过 22,调用方应在调用 NewNode 前完成配置。
	NodeBits uint8 = 10

	// StepBits 表示同一毫秒内序列号占用的比特数。
	// NodeBits 和 StepBits 总和不能超过 22,调用方应在调用 NewNode 前完成配置。
	StepBits uint8 = 12
)
View Source
var (

	// ErrInvalidBase58 表示 Base58 解析遇到未定义字符。
	// ParseBase58 返回该错误时结果值为 -1,调用方可使用 errors.Is 判断该错误。
	ErrInvalidBase58 = errors.New("invalid base58")
	// ErrInvalidBase32 表示 z-base-32 解析遇到未定义字符。
	// ParseBase32 返回该错误时结果值为 -1,调用方可使用 errors.Is 判断该错误。
	ErrInvalidBase32 = errors.New("invalid base32")
)

Functions

This section is empty.

Types

type ID

type ID int64

ID 表示 Snowflake 生成的唯一标识。

func ParseBase2

func ParseBase2(id string) (ID, error)

ParseBase2 将二进制字符串解析为 ID。

参数:

  • id: 待解析的二进制字符串。

返回:

  • ID: 解析成功时得到的 ID;解析失败时为 strconv.ParseInt 的中间结果,不应继续使用。
  • error: id 不是合法二进制整数或超出 int64 范围时返回 strconv.ParseInt 的错误。

func ParseBase32

func ParseBase32(b []byte) (ID, error)

ParseBase32 将 z-base-32 字节切片解析为 ID。

ParseBase32 使用本包内置的 z-base-32 字符表,不执行 int64 溢出检测。

参数:

  • b: 待解析的 z-base-32 编码字节切片。

返回:

  • ID: 解析成功时得到的 ID;遇到非法字符时返回 -1。
  • error: b 包含未定义字符时返回 ErrInvalidBase32,调用方可使用 errors.Is 判断。

func ParseBase36

func ParseBase36(id string) (ID, error)

ParseBase36 将 base36 字符串解析为 ID。

参数:

  • id: 待解析的 base36 字符串。

返回:

  • ID: 解析成功时得到的 ID;解析失败时为 strconv.ParseInt 的中间结果,不应继续使用。
  • error: id 不是合法 base36 整数或超出 int64 范围时返回 strconv.ParseInt 的错误。

func ParseBase58

func ParseBase58(b []byte) (ID, error)

ParseBase58 将 Base58 字节切片解析为 ID。

ParseBase58 使用本包内置字符表,不执行 int64 溢出检测。

参数:

  • b: 待解析的 Base58 编码字节切片。

返回:

  • ID: 解析成功时得到的 ID;遇到非法字符时返回 -1。
  • error: b 包含未定义字符时返回 ErrInvalidBase58,调用方可使用 errors.Is 判断。

func ParseBase64

func ParseBase64(id string) (ID, error)

ParseBase64 将 base64 字符串解析为 ID。

ParseBase64 先使用 base64.StdEncoding 解码,再按 Bytes 的十进制字节表示解析。

参数:

  • id: 待解析的 base64 字符串。

返回:

  • ID: 解析成功时得到的 ID;base64 解码失败时返回 -1,十进制解析失败时返回 ParseBytes 的结果。
  • error: id 不是合法 base64 字符串时返回解码错误;解码后内容不是合法十进制整数或超出 int64 范围时返回 strconv.ParseInt 的错误。

func ParseBytes

func ParseBytes(id []byte) (ID, error)

ParseBytes 将十进制字符串字节切片解析为 ID。

参数:

  • id: 待解析的十进制字符串字节切片。

返回:

  • ID: 解析成功时得到的 ID;解析失败时为 strconv.ParseInt 的中间结果,不应继续使用。
  • error: id 不是合法十进制整数或超出 int64 范围时返回 strconv.ParseInt 的错误。

func ParseInt64

func ParseInt64(id int64) ID

ParseInt64 将 int64 值转换为 ID。

参数:

  • id: 待转换的整数值。

返回:

  • ID: 与 id 数值相同的 Snowflake ID。

func ParseIntBytes

func ParseIntBytes(id [8]byte) ID

ParseIntBytes 将八字节大端整数表示转换为 ID。

参数:

  • id: 按 binary.BigEndian 编码的八字节整数数组。

返回:

  • ID: 从 id 还原得到的 Snowflake ID。

func ParseString

func ParseString(id string) (ID, error)

ParseString 将十进制字符串解析为 ID。

参数:

  • id: 待解析的十进制字符串。

返回:

  • ID: 解析成功时得到的 ID;解析失败时为 strconv.ParseInt 的中间结果,不应继续使用。
  • error: id 不是合法十进制整数或超出 int64 范围时返回 strconv.ParseInt 的错误。

func (ID) Base2

func (f ID) Base2() string

Base2 返回当前 ID 的二进制字符串表示。

参数:无。

返回:

  • string: 使用二进制编码的 ID 字符串。

func (ID) Base32

func (f ID) Base32() string

Base32 返回当前 ID 的 z-base-32 编码字符串。

Base32 使用本包内置的 z-base-32 字符表,不保证与标准库 base32 编码互通。

参数:无。

返回:

  • string: 使用 z-base-32 编码的 ID 字符串。

func (ID) Base36

func (f ID) Base36() string

Base36 返回当前 ID 的 base36 编码字符串。

参数:无。

返回:

  • string: 使用 base36 编码的 ID 字符串。

func (ID) Base58

func (f ID) Base58() string

Base58 返回当前 ID 的 Base58 编码字符串。

Base58 使用本包内置字符表,排除了 0、O、I 和 l 等易混淆字符。

参数:无。

返回:

  • string: 使用 Base58 编码的 ID 字符串。

func (ID) Base64

func (f ID) Base64() string

Base64 返回当前 ID 十进制字节表示的 base64 编码字符串。

参数:无。

返回:

  • string: 对 Bytes 返回值执行 base64.StdEncoding 后得到的字符串。

func (ID) Bytes

func (f ID) Bytes() []byte

Bytes 返回当前 ID 十进制字符串的字节表示。

参数:无。

返回:

  • []byte: ID 的十进制字符串字节切片。

func (ID) Int64

func (f ID) Int64() int64

Int64 返回当前 ID 的 int64 表示。

参数:无。

返回:

  • int64: ID 的原始整数值。

func (ID) IntBytes

func (f ID) IntBytes() [8]byte

IntBytes 返回当前 ID 的八字节大端整数表示。

参数:无。

返回:

  • [8]byte: 按 binary.BigEndian 写入的 ID 整数字节数组。

func (ID) MarshalJSON

func (f ID) MarshalJSON() ([]byte, error)

MarshalJSON 实现 JSON 序列化,将 ID 编码为带引号的十进制字符串。

参数:无。

返回:

  • []byte: JSON 字符串字面量形式的 ID。
  • error: 当前实现始终返回 nil。

func (ID) Node deprecated

func (f ID) Node() int64

Node 返回当前 ID 编码的节点编号。

Node 使用当前包级 nodeMask 和 nodeShift 解析 ID;如果解析时的全局配置与生成时不一致, 返回值可能不代表原始节点编号。

参数:无。

返回:

  • int64: ID 中编码的节点编号。

Deprecated: Node 依赖当前包级位布局解析旧 ID,保留用于兼容旧版本。

func (ID) Step deprecated

func (f ID) Step() int64

Step 返回当前 ID 编码的序列号。

Step 使用当前包级 stepMask 解析 ID;如果解析时的全局配置与生成时不一致, 返回值可能不代表原始序列号。

参数:无。

返回:

  • int64: ID 中编码的序列号。

Deprecated: Step 依赖当前包级位布局解析旧 ID,保留用于兼容旧版本。

func (ID) String

func (f ID) String() string

String 返回当前 ID 的十进制字符串表示。

参数:无。

返回:

  • string: 使用十进制编码的 ID 字符串。

func (ID) Time deprecated

func (f ID) Time() int64

Time 返回当前 ID 对应的绝对时间戳,单位为毫秒。

Time 使用当前包级 Epoch 和 timeShift 解析 ID;如果解析时的全局配置与生成时不一致, 返回值可能不代表原始生成时间。

参数:无。

返回:

  • int64: ID 对应的毫秒时间戳。

Deprecated: Time 依赖当前包级位布局解析旧 ID,保留用于兼容旧版本。

func (*ID) UnmarshalJSON

func (f *ID) UnmarshalJSON(b []byte) error

UnmarshalJSON 实现 JSON 反序列化,将带引号的十进制字符串解析为 ID。

调用方应使用非 nil 的 ID 指针接收结果;解析成功后才会覆盖接收者。

参数:

  • b: JSON 字节切片,必须是带引号的十进制字符串。

返回:

  • error: b 不是带引号字符串时返回 JSONSyntaxError;十进制内容无法解析或超出 int64 范围时返回 strconv.ParseInt 的错误。

type JSONSyntaxError

type JSONSyntaxError struct {
	// contains filtered or unexported fields
}

JSONSyntaxError 表示 JSON 反序列化时遇到非法 ID 形态的错误类型。

func (JSONSyntaxError) Error

func (j JSONSyntaxError) Error() string

Error 返回 JSONSyntaxError 的错误描述。

参数:无。

返回:

  • string: 包含原始 JSON 字节内容的错误消息。

type Node

type Node interface {
	// Generate 生成一个新的 Snowflake ID。
	//
	// 参数:无。
	//
	// 返回:
	//   - ID: 由当前节点生成的唯一 ID。
	Generate() ID
}

Node 定义生成 Snowflake ID 的节点能力。

func NewNode

func NewNode(nodeid int64) (Node, error)

NewNode 创建一个使用当前全局位布局的 Snowflake 节点。

NewNode 会按当前 Epoch、NodeBits 和 StepBits 初始化节点,并为兼容旧版本组件 解析方法重新计算包级派生掩码。调用方应为每个节点分配唯一的 nodeid,并避免在节点 创建后修改全局位宽配置。

参数:

  • nodeid: 节点编号,必须位于 0 到当前 NodeBits 可表示的最大值之间。

返回:

  • Node: 初始化完成的节点,可用于并发生成 ID。
  • error: NodeBits 与 StepBits 总和超过 22,或 nodeid 超出可用范围时返回错误。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL