idgen

package
v0.5.0 Latest Latest
Warning

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

Go to latest
Published: Mar 29, 2026 License: MIT Imports: 12 Imported by: 0

README

idgen

Go Reference

idgen 是 Genesis 的 ID 生成组件,位于业务层(L2)。它不只提供一种 ID,而是把四类常见能力收敛到同一个包里:

  • Generator:本地 Snowflake 风格 64bit ID
  • UUID():UUID v7 字符串 ID
  • Sequencer:基于 Redis 的按键递增序列号
  • Allocator:基于 Redis/Etcd 的 WorkerID 自动分配

如果你需要的是“数据库主键”“会话内消息序号”“实例唯一 WorkerID”这几类不同问题,idgen 提供的是一组可组合的解法,而不是单一算法。

接口边界和设计取舍见 Genesis IDGen:多种 ID 生成能力的设计与取舍,完整 API 文档见 go doc -all ./idgen

适用场景

  • Generator 生成趋势递增的整数主键,例如订单 ID、支付流水 ID。
  • UUID() 生成跨系统传递的字符串唯一标识。
  • Sequencer 为同一业务键生成严格递增序列,例如会话消息序号。
  • Allocator 为多个服务实例自动分配唯一 WorkerID,再交给 Generator 使用。

不适合的场景:

  • 需要按业务规则可逆解析的 ID。
  • 需要强撤销、会话态或持久化审计的“租约中心”。
  • 需要跨机房无限扩展位宽的自定义 Snowflake 协议。

快速开始

1. Snowflake 风格 ID
gen, err := idgen.NewGenerator(&idgen.GeneratorConfig{
	Mode:         idgen.GeneratorModeMultiDC,
	WorkerID:     1,
	DatacenterID: 0,
})
if err != nil {
	panic(err)
}

id, err := gen.Next()
if err != nil {
	panic(err)
}

Generator 当前支持两种位布局模式,并统一使用自定义 epoch 2024-01-01T00:00:00Z

  • single_dc41bit 时间戳 + 10bit worker + 12bit sequence
  • multi_dc41bit 时间戳 + 5bit datacenter + 5bit worker + 12bit sequence
2. UUID v7
id := idgen.UUID()

当你更在意跨系统唯一性和字符串兼容性,而不是整数主键和位结构时,直接用 UUID() 更合适。

3. Sequencer
seq, err := idgen.NewSequencer(&idgen.SequencerConfig{
	Driver:    "redis",
	KeyPrefix: "order:seq",
	Step:      1,
	TTL:       86400,
}, idgen.WithRedisConnector(redisConn))
if err != nil {
	panic(err)
}

nextID, err := seq.Next(ctx, "20260327")
if err != nil {
	panic(err)
}

Sequencer 当前只支持 Redis,适合“同一个业务键下递增”的场景,不适合代替全局主键。

4. Allocator + Generator
allocator, err := idgen.NewAllocator(&idgen.AllocatorConfig{
	Driver:    "etcd",
	KeyPrefix: "myapp:worker",
	MaxID:     512,
	TTL:       30,
}, idgen.WithEtcdConnector(etcdConn))
if err != nil {
	panic(err)
}
defer allocator.Stop()

workerID, err := allocator.Allocate(ctx)
if err != nil {
	panic(err)
}

go func() {
	if err := <-allocator.KeepAlive(ctx); err != nil {
		panic(err)
	}
}()

gen, err := idgen.NewGenerator(&idgen.GeneratorConfig{
	Mode:     idgen.GeneratorModeSingleDC,
	WorkerID: workerID,
})
if err != nil {
	panic(err)
}

这是 idgen 在分布式环境中的典型用法:Allocator 负责实例唯一 WorkerID,Generator 负责本地高吞吐生成 64bit ID。

选型建议

  • 优先用 Generator:需要整数主键、趋势递增、低延迟本地生成。
  • 优先用 UUID():需要字符串 ID、跨系统传递、无需数值解析。
  • 优先用 Sequencer:需要“同一个 key 下严格递增”。
  • 优先用 Allocator:WorkerID 不想手工配置,或实例数量会动态变化。

使用边界

  • Generator.Next()NextString() 会显式返回 error,不要忽略。
  • GeneratorConfig.Mode 决定 Snowflake 位布局,不要再用 DatacenterID == 0 隐式推断模式。
  • single_dc 模式下 WorkerID 范围是 0..1023,且 DatacenterID 必须为 0
  • multi_dc 模式下 WorkerID 范围是 0..31DatacenterID 范围是 0..31
  • Sequencer 当前不支持 Etcd。
  • Allocator.KeepAlive() 会启动后台保活并返回错误通道;如果不消费错误,租约丢失可能不会被上层及时感知。

Documentation

Overview

Package idgen 提供 Genesis L2 业务层的 ID 生成能力。

这个组件覆盖四类能力:

  • Generator: 本地 Snowflake 风格 64bit ID 生成器
  • UUID: UUID v7 字符串生成
  • Sequencer: 基于 Redis 的按键递增序列号
  • Allocator: 基于 Redis/Etcd 的 WorkerID 自动分配器

idgen 更像“多种 ID 能力的组合组件”,而不是单一算法封装。不同能力面向的问题不同:

  • 需要趋势递增、紧凑整数主键时使用 Generator
  • 需要跨系统字符串唯一标识时使用 UUID
  • 需要同一业务键下严格递增时使用 Sequencer
  • 需要为多个实例自动分配 WorkerID 时使用 Allocator

Generator 当前支持两种位布局模式:

  • single_dc: 41bit 时间戳、10bit worker、12bit sequence
  • multi_dc: 41bit 时间戳、5bit datacenter、5bit worker、12bit sequence

时间字段使用固定自定义 epoch 2024-01-01T00:00:00Z,调用 Next 或 NextString 时会显式返回错误, 以便调用方在时钟回拨等异常情况下做出停机、告警或重试决策。

Sequencer 当前只支持 Redis。Allocator 支持 Redis 和 Etcd,其中 KeepAlive 会启动后台保活并返回错误通道, Stop 负责释放租约资源,且实现应被视为幂等清理方法。

示例:

gen, _ := idgen.NewGenerator(&idgen.GeneratorConfig{WorkerID: 1})
id, _ := gen.Next()
fmt.Println(id)

Index

Constants

View Source
const (
	// MetricSnowflakeGenerated 雪花算法 ID 生成总数 (Counter)
	MetricSnowflakeGenerated = "idgen_snowflake_generated_total"

	// MetricSequenceGenerated 序列号生成总数 (Counter)
	MetricSequenceGenerated = "idgen_sequence_generated_total"
)

Metrics 指标常量定义

Variables

View Source
var (
	// ErrConnectorNil 连接器为空
	ErrConnectorNil = xerrors.New("idgen: connector is nil")

	// ErrAlreadyAllocated WorkerID 已分配
	ErrAlreadyAllocated = xerrors.New("idgen: worker id already allocated")

	// ErrWorkerIDExhausted WorkerID 已耗尽
	ErrWorkerIDExhausted = xerrors.New("idgen: no available worker id")

	// ErrClockBackwards 时钟回拨超过限制
	ErrClockBackwards = xerrors.New("idgen: clock moved backwards too much")

	// ErrInvalidInput 无效的输入
	ErrInvalidInput = xerrors.New("idgen: invalid input")

	// ErrLeaseExpired Etcd Lease 已过期
	ErrLeaseExpired = xerrors.New("idgen: lease expired")
)

Functions

func ParseGeneratorID

func ParseGeneratorID(id int64, mode GeneratorMode) (timestamp, datacenterID, workerID, sequence int64)

ParseGeneratorID 解析 Snowflake ID,返回其组成部分。 timestamp 为绝对 Unix 毫秒时间戳。

func UUID

func UUID() string

UUID 生成 UUID v7 字符串(时间排序,适合数据库主键)

使用示例:

id := idgen.UUID()

Types

type Allocator

type Allocator interface {
	// Allocate 分配 WorkerID(阻塞直到分配成功)
	Allocate(ctx context.Context) (int64, error)

	// KeepAlive 启动后台保活并返回错误通道
	// 保活失败时会向返回的通道发送错误
	KeepAlive(ctx context.Context) <-chan error

	// Stop 停止保活并释放资源
	Stop()
}

Allocator WorkerID 分配器接口 用于在集群环境中自动分配唯一的 WorkerID,避免手动配置冲突

func NewAllocator

func NewAllocator(cfg *AllocatorConfig, opts ...Option) (Allocator, error)

NewAllocator 创建 WorkerID 分配器 根据 cfg.Driver 选择 redis 或 etcd 实现

使用示例:

// Redis 分配器
allocator, _ := idgen.NewAllocator(&idgen.AllocatorConfig{
    Driver: "redis",
    MaxID:  512,
}, idgen.WithRedisConnector(redisConn))

workerID, _ := allocator.Allocate(ctx)
defer allocator.Stop()

go func() {
    if err := <-allocator.KeepAlive(ctx); err != nil {
        // 处理保活失败
    }
}()

type AllocatorConfig

type AllocatorConfig struct {
	// Driver 后端类型: "redis" | "etcd"
	Driver string `yaml:"driver" json:"driver"`

	// KeyPrefix 键前缀,默认 "genesis:idgen:worker"
	KeyPrefix string `yaml:"key_prefix" json:"key_prefix"`

	// MaxID 最大 ID 范围 [0, maxID),默认 1024
	MaxID int `yaml:"max_id" json:"max_id"`

	// TTL 租约 TTL(秒),默认 30
	TTL int `yaml:"ttl" json:"ttl"`
}

AllocatorConfig WorkerID 分配器配置

type Generator

type Generator interface {
	// Next 生成下一个 ID
	Next() (int64, error)

	// NextString 生成下一个 ID (字符串形式)
	NextString() (string, error)
}

Generator ID 生成器接口 提供高性能的分布式 ID 生成能力

func NewGenerator

func NewGenerator(cfg *GeneratorConfig, opts ...Option) (Generator, error)

NewGenerator 创建 ID 生成器 (Snowflake 实现)

使用示例:

gen, _ := idgen.NewGenerator(&idgen.GeneratorConfig{WorkerID: 1})
id, _ := gen.Next()

type GeneratorConfig

type GeneratorConfig struct {
	// Mode 位布局模式,默认 "multi_dc"。
	Mode GeneratorMode `yaml:"mode" json:"mode"`

	// WorkerID 工作节点 ID。
	// single_dc 模式范围 [0, 1023],multi_dc 模式范围 [0, 31]。
	WorkerID int64 `yaml:"worker_id" json:"worker_id"`

	// DatacenterID 数据中心 ID。
	// single_dc 模式下必须为 0,multi_dc 模式范围 [0, 31]。
	DatacenterID int64 `yaml:"datacenter_id" json:"datacenter_id"`
}

GeneratorConfig ID 生成器配置 (Snowflake)

type GeneratorMode added in v0.5.0

type GeneratorMode string

GeneratorMode Snowflake 位布局模式。

const (
	// GeneratorModeSingleDC 使用 41bit 时间戳 + 10bit worker + 12bit sequence。
	GeneratorModeSingleDC GeneratorMode = "single_dc"

	// GeneratorModeMultiDC 使用 41bit 时间戳 + 5bit datacenter + 5bit worker + 12bit sequence。
	GeneratorModeMultiDC GeneratorMode = "multi_dc"
)

type Option

type Option func(*options)

Option 组件初始化选项函数

func WithEtcdConnector

func WithEtcdConnector(conn connector.EtcdConnector) Option

WithEtcdConnector 注入 Etcd 连接器 目前仅用于 Allocator 组件

func WithLogger

func WithLogger(logger clog.Logger) Option

WithLogger 设置 Logger

func WithMeter

func WithMeter(m metrics.Meter) Option

WithMeter 注入指标 Meter(默认使用 metrics.Discard)

func WithRedisConnector

func WithRedisConnector(conn connector.RedisConnector) Option

WithRedisConnector 注入 Redis 连接器 用于 Allocator、Sequencer 等组件

type Sequencer

type Sequencer interface {
	// Next 为指定键生成下一个序列号
	Next(ctx context.Context, key string) (int64, error)

	// NextBatch 为指定键批量生成序列号
	NextBatch(ctx context.Context, key string, count int) ([]int64, error)

	// Set 直接设置序列号的值
	// 警告:此操作会覆盖现有值,请谨慎使用
	Set(ctx context.Context, key string, value int64) error

	// SetIfNotExists 仅当键不存在时设置序列号的值
	// 返回 true 表示设置成功,false 表示键已存在
	SetIfNotExists(ctx context.Context, key string, value int64) (bool, error)
}

Sequencer 序列号生成器接口 提供基于 Redis 的分布式序列号生成能力

func NewSequencer

func NewSequencer(cfg *SequencerConfig, opts ...Option) (Sequencer, error)

NewSequencer 创建序列号生成器(配置驱动,目前仅支持 Redis)

使用示例:

seq, _ := idgen.NewSequencer(&idgen.SequencerConfig{
    KeyPrefix: "im:seq",
    Step:      1,
    TTL:       3600, // 1 hour (秒)
}, idgen.WithRedisConnector(redisConn))

// IM 场景使用
id, _ := seq.Next(ctx, "alice")  // Alice 的消息序号
id, _ := seq.Next(ctx, "bob")    // Bob 的消息序号

type SequencerConfig

type SequencerConfig struct {
	// Driver 后端类型: "redis" | "etcd",默认 "redis"
	Driver string `yaml:"driver" json:"driver"`

	// KeyPrefix 键前缀
	KeyPrefix string `yaml:"key_prefix" json:"key_prefix"`

	// Step 步长,默认为 1
	Step int64 `yaml:"step" json:"step"`

	// MaxValue 最大值限制,达到后循环(0 表示不限制)
	MaxValue int64 `yaml:"max_value" json:"max_value"`

	// TTL 键过期时间(秒),0 表示永不过期
	TTL int64 `yaml:"ttl" json:"ttl"`
}

SequencerConfig 序列号生成器配置

Jump to

Keyboard shortcuts

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