竹简文档
初始化

雪花算法初始化

SnowflakeInit 作为内置节点初始化分布式唯一 ID 生成器

雪花算法初始化

SnowflakeInit 作为内置初始化节点,自动注册到节点管理器中,用于初始化雪花算法节点。

SnowflakeInit

register/init/init_snowflake.go
// 内置初始化节点函数
func SnowflakeInit(ctx context.Context) (any, error)

环境变量配置:

变量名说明默认值
SNOWFLAKE_DATACENTER_ID数据中心 ID根据机器特征自动生成
SNOWFLAKE_NODE_ID节点 ID根据机器特征自动生成

实现细节

register/init/init_snowflake.go
func SnowflakeInit(ctx context.Context) (any, error) {
    log := xLog.WithName(xLog.NamedINIT)
    log.Info(ctx, "初始化雪花算法节点")

    // 初始化默认节点
    if err := xSnowflake.InitDefaultNode(); err != nil {
        return nil, err
    }

    node := xSnowflake.GetDefaultNode()

    // 生成测试 ID 验证节点正常工作
    testID := node.MustGenerate()                          // 普通 ID(Gene=0)
    testGeneID := node.MustGenerate(xSnowflake.GeneSystem) // 基因 ID

    log.SugarDebug(ctx, "雪花算法节点初始化成功",
        "datacenter_id", node.DatacenterID(),
        "node_id", node.NodeID(),
        "test_id", testID.String(),
        "test_gene_id", testGeneID.String(),
    )

    // 返回节点实例,将被存入上下文
    return xSnowflake.GetDefaultNode(), nil
}

节点注册

Register 流程中,雪花算法作为内置节点自动注册:

register.go
func Register(ctx context.Context, nodeList []xRegNode.RegNodeList) *Reg {
    reg := newReg(ctx)

    reg.configInit()
    reg.loggerInit()

    // 内置节点:雪花算法
    reg.Init.Use(xCtx.SnowflakeNodeKey, xInit.SnowflakeInit)

    // 用户自定义节点
    for _, node := range nodeList {
        reg.Init.Use(node.Key, node.Node)
    }

    reg.Init.Exec()
    reg.engineInit()

    return reg
}

自动节点 ID 生成

若未配置环境变量,系统会根据机器特征自动生成节点 ID:

  1. MAC 地址:优先使用网卡 MAC 地址计算
  2. 主机名:MAC 地址不可用时使用主机名哈希

这确保了同一台机器在重启后仍能获得相同的节点 ID。

使用雪花算法

初始化后,雪花算法节点会通过上下文注入到每个 HTTP 请求:

import (
    xSnowflake "github.com/bamboo-services/bamboo-base-go/common/snowflake"
    xCtxUtil "github.com/bamboo-services/bamboo-base-go/common/utility/context"
)

func CreateUser(c *gin.Context) {
    // 获取标准上下文
    ctx := c.Request.Context()

    // 从上下文获取雪花算法节点
    node := xCtxUtil.GetSnowflakeNode(ctx)

    // 生成普通 ID
    userID := node.MustGenerate()

    // 生成带基因的 ID
    orderID := node.MustGenerate(xSnowflake.GeneOrder)
}

便捷函数

xCtxUtil 提供了便捷的 ID 生成函数:

// Panic 版本
id := xCtxUtil.MustGenerateSnowflakeID(ctx)
geneID := xCtxUtil.MustGenerateGeneSnowflakeID(ctx, xSnowflake.GeneUser)

// 错误返回版本
id, err := xCtxUtil.GenerateSnowflakeID(ctx)
geneID, err := xCtxUtil.GenerateGeneSnowflakeID(ctx, xSnowflake.GeneUser)

回退机制

GetSnowflakeNode 具有回退机制:

utility/ctxutil/snowflake.go
func GetSnowflakeNode(ctx context.Context) *xSnowflake.Node {
    value := ctx.Value(xCtx.SnowflakeNodeKey)
    if value != nil {
        if node, ok := value.(*xSnowflake.Node); ok {
            return node
        }
    }
    // 回退到默认节点(即使在非 HTTP 请求上下文中也能工作)
    return xSnowflake.GetDefaultNode()
}

这确保了即使在非 HTTP 请求上下文中(如定时任务、消息队列处理)也能正常生成 ID。

基因 ID

基因 ID 在标准雪花 ID 基础上增加了业务类型标识:

// 预定义基因类型
xSnowflake.GeneSystem  // 系统级 ID
xSnowflake.GeneUser    // 用户 ID
xSnowflake.GeneOrder   // 订单 ID
// ... 更多基因类型

解析基因:

id := node.MustGenerate(xSnowflake.GeneUser)

// 获取基因类型
gene := id.Gene()
fmt.Println(gene.String()) // "User"

注意事项

  • 该节点在 loggerInit 之后执行,确保日志记录器可用
  • 初始化失败会返回错误,导致 Exec() panic 并终止程序
  • 在分布式环境中,确保不同节点配置不同的 SNOWFLAKE_DATACENTER_IDSNOWFLAKE_NODE_ID

下一步

On this page