SnowflakeId.AutoRegister
是一个 C# 库,帮助你为 Snowflake ID 自动注册 WorkerId。
它不生成 Snowflake ID,仅为 WorkerId 的分配和注册提供支持。
支持多种存储机制(SQL Server、Redis 等),可轻松集成到任何使用 Snowflake ID 的库中。
SnowflakeId AutoRegister 是一个库,提供了一种简单的方法在 SnowflakeId 中自动注册 WorkerId。
它本身不生成 Snowflake Id,只帮助你自动注册 WorkerId。
- 多存储机制支持:Redis、SQL Server、MySQL 等
- 轻量级设计:无依赖,运行时动态加载驱动
- 灵活配置:通过链式 API 自定义注册逻辑
- 高兼容性:支持 .NET Standard 2.0,可在多种平台运行
- 简化开发流程:减少手动维护 WorkerId 的复杂性
- 高可靠性:支持 WorkerId 的自动续期,避免重复分配
- 为了兼容多种驱动以及多种版本,不包含任何驱动,避免过多依赖,运行时动态加载驱动
使用 NuGet 包管理工具快速安装:
Install-Package SnowflakeId.AutoRegister
-
Install-Package SnowflakeId.AutoRegister.Redis
-
Install-Package SnowflakeId.AutoRegister.SqlServer
注意:需自行安装 SQL Server 驱动:
Microsoft.Data.SqlClient
、System.Data.SqlClient
一般情况业务上都有安装对应驱动,如果没有安装,请自行安装Install-Package Microsoft.Data.SqlClient
或
Install-Package System.Data.SqlClient
-
Install-Package SnowflakeId.AutoRegister.MySql
注意:需自行安装 MySQL 驱动
MySql.Data
、MySqlConnector
一般情况业务上都有安装对应驱动,如果没有安装,请自行安装Install-Package MySql.Data
或
Install-Package MySqlConnector
以下是使用 SnowflakeId.AutoRegister 的基本示例
参考高级用法
使用 AutoRegisterBuilder
构建一个单例实例:
static readonly IAutoRegister AutoRegister = new AutoRegisterBuilder()
// 注册选项
// 使用以下行设置标识符。
// 推荐设置以区分单台机器上的多个应用程序
.SetExtraIdentifier(Environment.CurrentDirectory)
// 区分同路径exe,多个进程
// .SetExtraIdentifier(Environment.CurrentDirectory + Process.GetCurrentProcess().Id)S
// 日志配置
.SetLogMinimumLevel(SnowflakeId.AutoRegister.Logging.LogLevel.Debug)
.SetLogger((level, message, ex) => Console.WriteLine($"[{DateTime.Now}] [{level}] {message} {ex}"))
// 使用以下行设置 WorkerId 范围。
.SetWorkerIdScope(1, 31)
// 使用以下行设置注册选项。
// .SetRegisterOption(option => {})
// 使用以下行使用默认存储。
// 仅适用于开发使用、本地测试等。
//.UseDefaultStore()
// 使用以下行使用 Redis 存储。
.UseRedisStore("localhost:6379,allowAdmin=true")
// 使用以下行使用 SQL Server 存储。
//.UseSqlServerStore("Server=localhost;Database=SnowflakeTest;User Id=sa;Password=123456;")
// 使用以下行使用 MySQL 存储。
.UseMySqlStore("Server=localhost;Port=3306;Database=snowflaketest;Uid=test;Pwd=123456;SslMode=None;")
.Build();
通过 AutoRegister
实例获取 WorkerId
配置:
// 注册 WorkerId。
SnowflakeIdConfig config = AutoRegister.Register();
Console.WriteLine($"WorkerId: {config.WorkerId}");
在程序退出时,主动注销 WorkerId,确保资源释放:
//主动注销WorkId,程序退出时调用
//如果程序异常退出,下次启动时会自动尝试获取上次的WorkerId,如果获取失败会重新注册
AutoRegister.UnRegister();
//可以使用AppDomain.CurrentDomain.ProcessExit事件
AppDomain.CurrentDomain.ProcessExit += (_, _) =>
{
builder.UnRegister();
Console.WriteLine("Unregistered.");
};
//.Net Core及以上版本可以使用ApplicationStopping事件
applicationLifetime.ApplicationStopping.Register(() =>
{
builder.UnRegister();
Console.WriteLine("Unregistered.");
});
以下是集成 Yitter.IdGenerator 的示例:
var config = AutoRegister.Register();
var options = new IdGeneratorOptions
{
WorkerId = (ushort)config.WorkerId,
};
IIdGenerator idGenInstance = new DefaultIdGenerator(options);
long id = idGenInstance.NewLong();
Console.WriteLine($"Id: {id}");
将雪花Id工具库的生命周期托管到AutoRegister
实例中,以避免假死问题
。
原理:进程A注册了WorkerId 1,但是进程A因为各种原因(如生命周期太短、网络问题等)
导致无法及时续期,在其他进程看来此WorkerId已无效,进程B注册就会获得相同的WorkerId 1,在进程A恢复正常后,重新续期时会检测当前WorkId 1已被使用,会取消注册下次获取时会重新注册,
用法只需要调整Build
。
一下是Yitter.IdGenerator
的用法示例:
//IAutoRegister => IAutoRegister<xxx>
static readonly IAutoRegister<IIdGenerator> AutoRegister = new AutoRegisterBuilder()
//与其他配置一样
...
//重点在于这里
.Build<IIdGenerator>(config => new DefaultIdGenerator(new IdGeneratorOptions()
{
WorkerId = (ushort)config.WorkerId
}));
//获取Id
//确保每次都要使用`GetIdGenerator()`来获取`IdGenerator`实例,不要缓存,因为可能会重新注册
long id =autoRegister.GetIdGenerator().NewLong();
Console.WriteLine($"Id: {id}");
使用AutoRegister
托管Yitter.IdGenerator
的生命周期,与直接使用Yitter.IdGenerator
生成Id的性能对比。
BenchmarkDotNet v0.14.0, Windows 11 (10.0.26100.2314)
Intel Core i5-10400 CPU 2.90GHz, 1 CPU, 12 logical and 6 physical cores
.NET SDK 9.0.100
[Host] : .NET 6.0.33 (6.0.3324.36610), X64 RyuJIT AVX2
.NET 6.0 : .NET 6.0.33 (6.0.3324.36610), X64 RyuJIT AVX2
.NET 8.0 : .NET 8.0.8 (8.0.824.36612), X64 RyuJIT AVX2
| Method | Job | Runtime | Mean | Error | StdDev | Median | Allocated |
|---------------------------------|----------|----------|---------:|----------:|----------:|---------:|----------:|
| IdGeneratorUtil_100 | .NET 6.0 | .NET 6.0 | 1.697 ms | 0.2230 ms | 0.6575 ms | 1.951 ms | 1 B |
| AutoRegisterIdGeneratorUtil_100 | .NET 6.0 | .NET 6.0 | 1.697 ms | 0.2228 ms | 0.6568 ms | 1.950 ms | 1 B |
| IdGeneratorUtil_100 | .NET 8.0 | .NET 8.0 | 1.697 ms | 0.2230 ms | 0.6575 ms | 1.951 ms | 1 B |
| AutoRegisterIdGeneratorUtil_100 | .NET 8.0 | .NET 8.0 | 1.698 ms | 0.2228 ms | 0.6570 ms | 1.951 ms | 1 B |
-
Q: 为什么需要自动注册 WorkerId?
-
A: Snowflake ID 需要 WorkerId 来生成唯一的 ID。自动注册 WorkerId 可以减少手动维护的复杂性。
-
Q: 如果程序崩溃了,WorkerId 会被释放吗?
-
A: 不会。WorkerId存在生命周期,程序异常退出时,下次启动会尝试注册上一次的 WorkerId。如果失败,则重新注册新的 WorkerId。
-
Q: "假死问题"是什么?
-
A: 例如:进程A注册了WorkerId,但是进程A因为各种原因(如生命周期太短、网络问题等) 导致无法及时续期,在其他进程看来此WorkerId已无效,进程B注册就会获得相同的WorkerId,如果进程A恢复正常,此时进程A和进程B都会使用相同的WorkerId,导致ID重复 解决方案看高级用法
-
Q: 如何避免同文件多进程重复分配 WorkerId?
-
A: 在 SetExtraIdentifier 中添加进程相关的标识符,例如当前进程 ID。
-
Q: 默认存储机制适合生产环境吗?
-
A: 默认存储机制仅适合开发和本地测试(为了保持一致性)。在生产环境中,建议使用 Redis、SQL Server、MySql等等。
欢迎提交拉取请求!在贡献代码前,请遵循以下步骤:
- Fork 本仓库并创建新分支。
- 确保代码通过所有测试,并保持与主分支同步。
- 如果有重大更改,请先打开一个 Issue 讨论你想要更改的内容。 请确保适当更新测试。
- 提交 PR 并描述所做的更改。
克隆仓库:
git clone https://github.com/LemonNoCry/SnowflakeId.AutoRegister.git
导航到项目目录:
cd SnowflakeId.AutoRegister
恢复包:
dotnet restore
构建项目:
dotnet build
This project is licensed under the MIT License.