RuoVea.ExIdGen 10.0.0.3

dotnet add package RuoVea.ExIdGen --version 10.0.0.3
                    
NuGet\Install-Package RuoVea.ExIdGen -Version 10.0.0.3
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="RuoVea.ExIdGen" Version="10.0.0.3" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RuoVea.ExIdGen" Version="10.0.0.3" />
                    
Directory.Packages.props
<PackageReference Include="RuoVea.ExIdGen" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add RuoVea.ExIdGen --version 10.0.0.3
                    
#r "nuget: RuoVea.ExIdGen, 10.0.0.3"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package RuoVea.ExIdGen@10.0.0.3
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=RuoVea.ExIdGen&version=10.0.0.3
                    
Install as a Cake Addin
#tool nuget:?package=RuoVea.ExIdGen&version=10.0.0.3
                    
Install as a Cake Tool

🆔 RuoVea.ExIdGen

分布式唯一 ID 生成器 — 基于雪花漂移算法(移植自 yitter/idgenerator),生成 64 位长整型 ID、带前缀字符串 ID、以及基于时间戳的自增编号,内置中、英、法、日、繁体中文、粤语、越南语等 8 种语言的异常提示。


📖 目录


📋 概览

RuoVea.ExIdGen 为 .NET 开发者提供开箱即用的分布式唯一 ID 生成能力,基于雪花(Snowflake)算法并通过漂移补偿机制解决时钟回拨问题。

 ┌──────────────────────────────────────────────────────────┐
 │                    RuoVea.ExIdGen                         │
 ├──────────────────────────────────────────────────────────┤
 │  ID 生成方式                                              │
 │  ├─ Id (static long)           → 64 位 Snowflake ID      │
 │  ├─ IdStr(prefix)              → 带前缀字符串 ID          │
 │  ├─ No(format)                 → 时间戳自增长整型编号     │
 │  └─ NoStr(format)              → 时间戳自增字符串编号     │
 │                                                          │
 │  算法模式                                                 │
 │  ├─ Method 1 (默认) — 雪花漂移算法,时钟回拨补偿          │
 │  ├─ Method 2        — 传统雪花算法,时钟回拨抛出异常      │
 │  └─ Method 3        — 漂移算法 + DataCenter + 秒级时间戳 │
 │                                                          │
 │  配置方式                                                 │
 │  ├─ Configure(options)         → IdGeneratorOptions 对象 │
 │  ├─ Configure(workerId, seq)   → 精简配置                │
 │  └─ Configure(IConfiguration)  → appsettings.json 驱动   │
 ├──────────────────────────────────────────────────────────┤
 │  国际化: zh-CN | zh-TW | zh-HK | en-US | fr-FR |          │
 │           ja-JP | vi-VN                                  │
 └──────────────────────────────────────────────────────────┘

设计原则

原则 说明
零配置启动 未调用 Configure 时自动初始化 WorkerId=0 的默认实例
漂移补偿 Method 1 在单毫秒内序列号耗尽时自动"借用"下一毫秒,容忍短期时钟回拨
唯一性保证 WorkerId(机器码) + 时间戳 + 自增序列号三元组保证全局唯一
参数校验 初始化时对 WorkerIdSeqBitLengthBaseTime 等参数进行全面校验,抛出含本地化消息的异常

📦 安装

.NET CLI

# .NET 8.0
dotnet add package RuoVea.ExIdGen --version 8.0.1.1

# .NET 10.0
dotnet add package RuoVea.ExIdGen --version 10.0.0.2

Package Manager

Install-Package RuoVea.ExIdGen -Version 8.0.1.1

PackageReference

<PackageReference Include="RuoVea.ExIdGen" Version="8.0.1.1" />

支持的 Target Framework

TFM 最低版本
net8.0 8.0.1.1
net10.0 10.0.0.2

⚡ 30 秒快速开始

1. 导入命名空间

using RuoVea.ExIdGen;                   // IdGenerator, ConfigureOption
using RuoVea.ExIdGen.Contract;          // IdGeneratorOptions, IIdGenerator

2. 配置并生成第一个 ID

// ① 配置(应用启动时执行一次)
IdGenerator.Configure(workerId: 1, seqBitLength: 6);

// ② 生成 64 位 Snowflake ID
long id = IdGenerator.Id;
Console.WriteLine(id); // 如: 745635281972854784

// ③ 生成带前缀的字符串 ID
string orderId = IdGenerator.IdStr("ORDER_");
Console.WriteLine(orderId); // "ORDER_745635281972854784"

3. 通过 appsettings.json 配置

{
  "IdGenerator": {
    "WorkerId": "1",
    "SeqBitLength": "6"
  }
}
// 在 Program.cs / Startup.cs 中
var configuration = builder.Configuration;
IdGenerator.Configure(configuration);

注意: Configure(IConfiguration) 方法存在 Bug——当配置文件中未提供 SeqBitLength 时,会将 workerId 错误赋值为 6(而非将 seqBitLength 赋值为 6)。请务必在配置文件中显式提供 SeqBitLength 字段,或改用 Configure(ushort, byte) 重载。

30 秒内你完成了: 导入命名空间 → 配置 WorkerId → 生成 Snowflake ID → 生成带前缀字符串 ID。


🧩 核心场景

场景一:生成 Snowflake ID(长整型)

┌──────────────┐    IdGenerator.Id    ┌───────────────────┐
│  WorkerId=1  │ ─────────────────▶  │  745635281972854784 │
│  (机器码)     │                      │  (64-bit long)      │
└──────────────┘                      └───────────────────┘
用例: 数据库主键、消息队列消息ID、全局唯一标识
// 生成单个 ID
long userId = IdGenerator.Id;

// 批量生成(用于数据迁移等场景)
var ids = new List<long>();
for (int i = 0; i < 1000; i++)
{
    ids.Add(IdGenerator.Id);
}

// 验证唯一性
bool allUnique = ids.Distinct().Count() == ids.Count;
Console.WriteLine(allUnique); // True

场景二:生成带前缀的字符串 ID

┌──────────────┐  IdGenerator.IdStr("ORDER_")  ┌──────────────────────────┐
│  WorkerId=1  │ ──────────────────────────▶  │  "ORDER_745635281972854784" │
└──────────────┘                                └──────────────────────────┘
用例: 订单编号、物流单号、工单编号(人类可读前缀 + 机器唯一后缀)
// 无前缀
string id1 = IdGenerator.IdStr();
// → "745647812025876480"

// 业务前缀——订单
string orderId = IdGenerator.IdStr("ORD");
// → "ORD745647812025876480"

// 业务前缀——支付流水
string paymentId = IdGenerator.IdStr("PAY");
// → "PAY745647812025876481"

⚠️ 注意: IdStr 仅做字符串拼接(prefix + NextId()),不保证前缀在分布式场景下的唯一性。如需确保前缀 + 业务语义的全局唯一,应在业务层设计前缀规范。


场景三:生成基于时间的自增编号

┌──────────┐   IdGenerator.No("yyyyMMddHHmmss")   ┌──────────────────────┐
│  当前时间  │ ─────────────────────────────────▶  │  202602231508451234  │
│  随机后缀  │                                       │  (时间戳 + 4位随机)  │
└──────────┘                                       └──────────────────────┘
用例: 流水号、批次号、临时编号(时间可读 + 简易去重)
// 默认格式 yyyyMMddHHmmss + 4 位随机数
string noStr = IdGenerator.NoStr();
// → "202602231508451234"

long noLong = IdGenerator.No();
// → 202602231508459876

// 自定义时间格式
string shortNo = IdGenerator.NoStr("yyMMddHHmm");
// → "2602231508" + 随机后缀

⚠️ 使用注意: No / NoStr 使用共享的 static Random + 自增计数器 _sn 生成后缀,单实例内线程安全。该格式非 Snowflake ID,不保证跨实例唯一性。


场景四:三种算法模式切换

// 模式 1(默认): 雪花漂移算法 — 时钟回拨自动补偿,推荐用于生产环境
IdGenerator.Configure(new IdGeneratorOptions
{
    WorkerId = 1,
    Method = 1                     // 漂移补偿
});

// 模式 2: 传统雪花算法 — 严格单调递增,遇到时钟回拨直接抛出异常
IdGenerator.Configure(new IdGeneratorOptions
{
    WorkerId = 2,
    Method = 2                     // 传统雪花
});

// 模式 3: 漂移算法 + DataCenter + 秒级时间戳 — 适用于多数据中心、低精度场景
IdGenerator.Configure(new IdGeneratorOptions
{
    WorkerId = 1,
    DataCenterId = 3,
    DataCenterIdBitLength = 2,
    TimestampType = 1,             // 秒级时间戳
    Method = 1                     // 漂移补偿(Method=1 时自动选择 M3 实现)
});
模式 时钟回拨策略 适用场景
Method 1 SnowWorkerM1 漂移补偿(借用下一毫秒 + 回拨次序 1~4) 生产环境(推荐)
Method 2 SnowWorkerM2 抛出异常 严格时钟同步环境
Method 3 SnowWorkerM3 漂移补偿 + DataCenter + 秒级时间戳 多数据中心 / 低精度

⚠️ 注意: 当 Method=1DataCenterIdBitLength > 0TimestampType = 1 时,自动选择 SnowWorkerM3 实现。


场景五:通过 IConfiguration 配置

// appsettings.json
{
  "IdGenerator": {
    "WorkerId": "3",
    "SeqBitLength": "8"
  }
}

// 初始化
var builder = WebApplication.CreateBuilder(args);
IdGenerator.Configure(builder.Configuration);

Bug 警告: ConfigureOption.Configure(IConfiguration) 在第 61 行存在赋值错误——当 SeqBitLength 解析失败时执行的逻辑是 workerId = 6 而非 seqBitLength = 6。这意味着:如果你的配置文件中未显式提供 SeqBitLengthworkerId 将被错误覆盖为 6,而 seqBitLength 保持默认值 6。请务必在配置文件中同时提供 WorkerIdSeqBitLength,避免触发此 Bug。


场景六:使用 IIdGenerator 接口

// 获取底层 IIdGenerator 实例
IIdGenerator generator = IdGenerator.IdGenInstance;

// 生成 ID
long id = generator.NewLong();

// 注册漂移事件回调(示例)
generator.GenIdActionAsync = (arg) =>
{
    Console.WriteLine(
        $"ActionType={arg.ActionType}, WorkerId={arg.WorkerId}, " +
        $"TimeTick={arg.TimeTick}, OverCostCount={arg.OverCostCountInOneTerm}");
};

⚠️ 死代码警告: SnowWorkerM1 中的 BeginOverCostActionEndOverCostActionBeginTurnBackActionEndTurnBackAction 四个方法开头均有 return; 语句,导致 GenIdActionAsync 回调永远无法被触发。注册的回调不会收到任何通知。在修复前,不要依赖回调机制来监控 ID 生成状态。


⚙️ 配置选项详解

IdGeneratorOptions

参数 类型 约束 默认值 说明
Method short 1 / 2 1 算法模式:1=漂移补偿,2=传统雪花
BaseTime DateTime 不能超过当前系统时间 2020-02-20 02:20:02.020 (UTC) 基准时间(UTC),ID 的时间戳部分为相对此时间的偏移
WorkerId ushort 0 ~ 2^WorkerIdBitLength-1 0 机器码,必须全局唯一(或同 DataCenterId 内唯一)
WorkerIdBitLength byte [1, 19](实际 ≤16) 6 机器码位长,决定 WorkerId 最大值
SeqBitLength byte [3, 21](建议 ≥4) 6 序列数位长,决定每毫秒基础生成 ID 个数
MaxSeqNumber int [MinSeqNumber, 2^SeqBitLength-1] 0(= 2^SeqBitLength-1) 最大序列数,0 表示取理论最大值
MinSeqNumber ushort [5, MaxSeqNumber] 5 最小序列数,0-4 为保留位(回拨/手工预留)
TopOverCostCount int 推荐 500~10000 2000 最大漂移次数,超出后等待时间对齐
DataCenterId uint 0 ~ 2^DataCenterIdBitLength-1 0 数据中心 ID,Method 3 使用
DataCenterIdBitLength byte 0 数据中心 ID 位长,0 表示不使用
TimestampType byte 0(毫秒)/ 1(秒) 0 时间戳精度,秒级时放大时间位长到 31

位长约束

WorkerIdBitLength + DataCenterIdBitLength + SeqBitLength ≤ 22(毫秒模式)
WorkerIdBitLength + DataCenterIdBitLength + SeqBitLength ≤ 31(秒级模式)

Configure 重载

重载 说明
Configure(IdGeneratorOptions) 完整配置,传入所有选项
Configure(ushort workerId, byte seqBitLength) 精简配置,仅设置 WorkerId 和 SeqBitLength
Configure(IConfiguration) 从 IConfiguration 读取 "IdGenerator" 节点

🛡️ 错误处理与日志

异常体系

DefaultIdGenerator 构造函数在参数不合法时抛出 ApplicationException(含本地化消息):

// 未调用 Configure 时自动初始化为 WorkerId=0(不抛异常)
long id = IdGenerator.Id; // ✅ 自动初始化

// WorkerId 超出位长限制 → ApplicationException
IdGenerator.Configure(new IdGeneratorOptions { WorkerId = 64, WorkerIdBitLength = 6 });
// → "workerid错误。(范围:[0,63])"

// BaseTime 超过当前时间 → ApplicationException
IdGenerator.Configure(new IdGeneratorOptions { BaseTime = DateTime.UtcNow.AddDays(1) });
// → "basetime错误。"

// WorkerIdBitLength = 0 → ApplicationException
IdGenerator.Configure(new IdGeneratorOptions { WorkerIdBitLength = 0 });
// → "workeridbitlength错误。(范围:[1,21])"

Method 2 时钟回拨异常

IdGenerator.Configure(new IdGeneratorOptions { Method = 2, WorkerId = 1 });

try
{
    long id = IdGenerator.Id;
}
catch (Exception ex)
{
    // "xxx毫秒的时间错误" — Method 2 遇到时钟回拨时抛出
    _logger.LogError(ex, "Snowflake 时钟回拨,生成的 ID 可能重复");
    // ⚠️ 此时应切换到 Method 1 或暂停服务等待时钟恢复
}

推荐日志模式

using Microsoft.Extensions.Logging;

public class IdGeneratorService
{
    private readonly ILogger<IdGeneratorService> _logger;

    public IdGeneratorService(ILogger<IdGeneratorService> logger) => _logger = logger;

    /// <summary>
    /// 带日志的 ID 生成器初始化
    /// </summary>
    public void Initialize(ushort workerId, byte seqBitLength = 6)
    {
        try
        {
            IdGenerator.Configure(workerId, seqBitLength);
            _logger.LogInformation(
                "ExIdGen 初始化成功: WorkerId={WorkerId}, SeqBitLength={SeqBitLength}",
                workerId, seqBitLength);
        }
        catch (ApplicationException ex)
        {
            _logger.LogError(ex, "ExIdGen 初始化失败,参数校验未通过");
            throw;
        }
    }

    /// <summary>
    /// 安全生成 ID(Method 2 时钟回拨兜底)
    /// </summary>
    public long NextIdSafe()
    {
        try
        {
            return IdGenerator.Id;
        }
        catch (Exception ex) when (ex.Message.Contains("毫秒的时间错误"))
        {
            _logger.LogWarning(ex, "传统雪花模式遭遇时钟回拨,考虑切换到 Method=1");
            throw;
        }
    }
}

🧵 线程安全

组件 线程安全 说明
IdGenerator.Id ⚠️ 加锁保证 SnowWorkerM1.NextId() 使用 lock(_SyncLock) 保证临界区互斥
IdGenerator.IdStr ⚠️ 加锁保证 委托给 NextId(),同上
IdGenerator.No / NoStr ✅ 加锁保证 共享 static Random + 独立 lock,线程安全
ConfigureOption.Configure ✅ 是 NextId() 惰性初始化使用双重检查锁(lock(_initLock)),线程安全
SnowWorkerM1 / M2 / M3 ⚠️ 全局锁 _SyncLockstatic readonly——所有实例共享同一把锁,多实例也串行执行
DefaultIdGenerator ⚠️ 实例安全,但其委托的 _SnowWorker.NextId() 受全局锁限制
i18n ✅ 是 ResourceManager 线程安全

⚠️ 重要: 全局锁限制: SnowWorkerM1._SyncLockstatic readonly,所有 DefaultIdGenerator 实例共享同一把锁。多实例场景下 ID 生成完全串行化。如需更高吞吐量,请在应用层做 worker 分片。

// ✅ 正确: 启动时配置
public static void Main(string[] args)
{
    IdGenerator.Configure(workerId: 1, seqBitLength: 6); // ← 先配置
    var app = BuildApp(args);
    app.Run();
}

// ❌ 错误: 延迟配置(并发访问可能创建多个实例)
Task.Run(() => IdGenerator.Configure(1, 6));
Task.Run(() => { var id = IdGenerator.Id; });   // ← 竞态!

⚠️ 重要(2): 全局锁: SnowWorkerM1._SyncLock 被声明为 protected static object _SyncLock = new object()。这意味着即使你创建了多个 DefaultIdGenerator 实例(不同的 WorkerId),它们仍共享同一把锁,所有 ID 生成被全局串行化。这是设计权衡——确保时间戳和序列号在进程内绝对单调递增,但是以吞吐量为代价。

⚠️ 重要(3): 不要声称"无锁"NextId() 明确使用 lock(_SyncLock) 同步,且 No / NoStr 也使用独立 lock。这不是无锁实现。


📊 算法速查表

方法 输入 输出 用途
IdGenerator.Id static getter long (64-bit) 数据库主键、全局唯一 ID
IdGenerator.IdStr static getter string prefix string 人类可读的业务编号
IdGenerator.No static getter string format long 时间可读的长整型流水号
IdGenerator.NoStr static getter string format string 时间可读的字符串流水号
IIdGenerator.NewLong 实例方法 long (64-bit) 通过接口直接访问底层生成器
IdGenerator.Configure static options / workerId+seq / IConfiguration void 初始化/重配置 ID 生成器

ID 结构(Method 1,默认位长配置)

┌─────────────────────────────────────────────────────────────┐
│  63 ......................... 12 │ 11 .... 6 │ 5 ........ 0 │
│         时间戳偏移 (52 bit)      │ WorkerId  │  序列号      │
│                                  │  (6 bit)  │  (6 bit)    │
└─────────────────────────────────────────────────────────────┘
  WorkerIdBitLength=6, SeqBitLength=6, TimestampShift=12

🌍 国际化

错误消息支持以下语言,根据 CultureInfo.CurrentUICulture 自动切换:

语言 区域代码
简体中文 zh-CN
繁体中文(台湾) zh-TW
粤语(香港) zh-HK
英语 en-US
法语 fr-FR
日语 ja-JP
越南语 vi-VN
// 当前线程 UI 文化为 fr-FR 时:
// ApplicationException → 对应法语的 "basetime错误。"(具体内容取决于 .resx 翻译)
IdGenerator.Configure(new IdGeneratorOptions { BaseTime = DateTime.UtcNow.AddDays(1) });

可通过 I18nConverter.ConvertResxToJson() 将资源内容导出为 JSON(需 NET5_0_OR_GREATER)。


🗺️ 版本迁移指南

从手动管理 Snowflake 迁移

旧代码模式 迁移到 RuoVea.ExIdGen
手动实现 Snowflake + Stopwatch / DateTime 计算 IdGenerator.Id
手动维护 AtomicLong 序列号 + 时钟回拨处理 IdGenerator.Configure(workerId, seqBitLength)
appsettings.json + 手动解析 WorkerId IdGenerator.Configure(IConfiguration)
GUID / UUID 作为分布式 ID IdGenerator.Id(64-bit,体积减半,有序递增)

v8.0.x → v10.0.x

  • API 无变化。v10.0.x 仅在 net10.0 TFM 上编译,所有公开 API 签名保持一致。
  • 依赖 Microsoft.Extensions.Configuration.Binder 版本从 8.0.2 升级到 10.0.8

📄 License

MIT License © RuoVea

原始算法版权:yitter/idgenerator (MIT)


🔗 相关资源: NuGet Gallery · 问题反馈

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on RuoVea.ExIdGen:

Package Downloads
RuoVea.ExSugar

Sqlsugar扩展 快速注入,支持简体中文、繁体中文、粤语、日语、法语、英语.使用方式:service.AddSqlsugar();继承RestFulLog 重写异常日志,操作日志,差异日志

RuoVea.ExWeb

CorsUrls、IPLimit、SafeIps、Jwt 配置

RuoVea.QuartzNetUI

QuartzNet UI界面 执行脚本地址:https://gitee.com/starry123/ruovea-quartznet-ui/tree/develop/Doc/Sql

RuoVea.KM

RuoVea.KM 提供完整的授权管理系统: - **LicenseInfo**:授权信息实体类,包含授权ID、客户名称、绑定机器指纹、有效期等属性 - **LicenseManager**:授权管理通用类,提供授权码生成、验证、激活等功能 - **MachineFingerprint**:机器硬件指纹生成器,基于CPU、硬盘、MAC地址和主板序列号 该库提供了简单易用的 API 接口,支持 .NET 5/6/7/8/9/10,适用于各种国密加密和授权管理场景

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
10.0.0.3 220 6/24/2026
10.0.0.2 508 5/28/2026
10.0.0.1 916 11/21/2025
9.0.0.1 1,589 11/21/2025
9.0.0 607 7/25/2025
8.0.1.2 347 6/24/2026
8.0.1.1 4,398 11/21/2025
8.0.1 6,338 8/26/2024
8.0.0 565 11/24/2023
7.0.1.1 4,476 11/21/2025
7.0.1 7,591 8/26/2024
7.0.0 305 7/23/2024
6.0.1.2 5,391 11/21/2025
6.0.1 15,795 8/26/2024
5.0.3.2 132 5/28/2026
5.0.3.1 650 11/21/2025
5.0.3 691 8/26/2024
2.1.1.2 423 11/21/2025
2.0.0.1 433 11/21/2025
2.0.0 236 9/22/2024
Loading failed