SnowflakeId.AutoRegister
is a lightweight C# library designed for automatic registration of WorkerId in SnowflakeId
systems. It supports various storage mechanisms, such as SQL Server, Redis, and MySQL.
Note: This library does not generate Snowflake IDs itself. It is only responsible for WorkerId assignment and
registration, making it compatible with any framework or library using Snowflake IDs.
- Multi-storage support: Compatible with Redis, SQL Server, MySQL, and more.
- Lightweight design: Avoids unnecessary dependencies; drivers are loaded dynamically at runtime.
- Flexible configuration: Chainable API to customize registration logic.
- High compatibility: Supports .NET Standard 2.0, allowing cross-platform usage.
- Simplifies development: Reduces complexity in managing WorkerId for distributed systems.
- High reliability: Supports automatic renewal of WorkerId to prevent duplicate assignments.
SnowflakeId.AutoRegister
simplifies the process of automatically registering WorkerIds in SnowflakeId systems.
- .NET Standard 2.0 or later.
- Storage driver (e.g., Redis, SQL Server, MySQL).
- Suitable for applications requiring unique WorkerIds for SnowflakeId generation.
Install the core package via NuGet:
Install-Package SnowflakeId.AutoRegister
-
Install-Package SnowflakeId.AutoRegister.Redis
-
Install-Package SnowflakeId.AutoRegister.SqlServer
Note: You must manually install the SQL Server driver if not already available:
Install-Package Microsoft.Data.SqlClient
or
Install-Package System.Data.SqlClient
-
Install-Package SnowflakeId.AutoRegister.MySql
Note: You must manually install the MySQL driver if not already available:
Install-Package MySql.Data
or
Install-Package MySqlConnector
Refer to Advanced Usage
Create a singleton IAutoRegister
instance using AutoRegisterBuilder
:
static readonly IAutoRegister AutoRegister = new AutoRegisterBuilder()
// Set unique identifiers to distinguish applications.
.SetExtraIdentifier(Environment.CurrentDirectory)
// Optionally, distinguish processes with the same path.
// .SetExtraIdentifier(Environment.CurrentDirectory + Process.GetCurrentProcess().Id)
// Set Logger.
.SetLogMinimumLevel(SnowflakeId.AutoRegister.Logging.LogLevel.Debug)
.SetLogger((level, message, ex) => Console.WriteLine($"[{DateTime.Now}] [{level}] {message} {ex}"))
// Set the range for WorkerIds.
.SetWorkerIdScope(1, 31)
// Use a default storage mechanism (for development only).
//.UseDefaultStore()
// Use Redis as the storage.
.UseRedisStore("localhost:6379,allowAdmin=true")
// Use SQL Server as the storage.
//.UseSqlServerStore("Server=localhost;Database=SnowflakeTest;User Id=sa;Password=123456;")
// Use MySQL as the storage.
//.UseMySqlStore("Server=localhost;Port=3306;Database=snowflaketest;Uid=test;Pwd=123456;SslMode=None;")
.Build();
Retrieve the WorkerId configuration using the Register
method:
SnowflakeIdConfig config = AutoRegister.Register();
Console.WriteLine($"WorkerId: {config.WorkerId}");
Unregister WorkerId to release resources when the application exits:
AutoRegister.UnRegister();
// Use AppDomain events for graceful shutdown.
AppDomain.CurrentDomain.ProcessExit += (_, _) =>
{
AutoRegister.UnRegister();
Console.WriteLine("Unregistered.");
};
// For .NET Core and later, use IHostApplicationLifetime events.
applicationLifetime.ApplicationStopping.Register(() =>
{
AutoRegister.UnRegister();
Console.WriteLine("Unregistered.");
});
Here's how to integrate SnowflakeId.AutoRegister
with 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($"Generated ID: {id}");
Delegate the lifecycle of the Snowflake ID tool library to the AutoRegister
instance to avoid the "zombie problem".
Principle: Process A registers WorkerId 1, but due to various reasons (such as a short lifecycle, network issues, etc.), it cannot renew in time. In other processes, this
WorkerId is considered invalid, and process B will register the same WorkerId 1. When process A recovers, it will detect that WorkerId 1 is already in use and will cancel the
registration, re-registering the next time it is acquired.
Usage only requires adjusting Build
.
Here is an example of using Yitter.IdGenerator
:
//IAutoRegister => IAutoRegister<xxx>
static readonly IAutoRegister<IIdGenerator> AutoRegister = new AutoRegisterBuilder()
// Same as other configurations
...
// The key point is here
.Build<IIdGenerator>(config => new DefaultIdGenerator(new IdGeneratorOptions()
{
WorkerId = (ushort)config.WorkerId
}));
//Get Id
// Ensure to use `GetIdGenerator()` to get the `IdGenerator` instance each time, do not cache it, as it may re-register
long id =autoRegister.GetIdGenerator().NewLong();
Console.WriteLine($"Id: {id}");
Comparing the performance of using AutoRegister
to manage the lifecycle of Yitter.IdGenerator
versus directly using Yitter.IdGenerator
to generate IDs.
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: Why do we need to auto-register WorkerId?
-
A: Snowflake ID requires WorkerId to generate unique IDs. Auto-registering WorkerId can reduce the complexity of manual maintenance.
-
Q: Will WorkerId be released if the program crashes?
-
A: No. WorkerId has a lifecycle. If the program exits abnormally, it will try to register the previous WorkerId on the next startup. If it fails, it will re-register a new WorkerId.
-
Q: What is the "zombie problem"?
-
A: For example, process A registers a WorkerId, but due to various reasons (such as a short lifecycle, network issues, etc.), it cannot renew in time. In other processes, this WorkerId is considered invalid, and process B will register the same WorkerId. If process A recovers, both process A and process B will use the same WorkerId, causing ID duplication. See Advanced Usage for the solution.
-
Q: How to avoid multiple processes in the same file from being assigned the same WorkerId?
-
A: Add a process-related identifier in SetExtraIdentifier, such as the current process ID.
-
Q: Is the default storage mechanism suitable for production environments?
-
A: The default storage mechanism is only suitable for development and local testing (to maintain consistency). In production environments, it is recommended to use Redis, SQL Server, MySQL, etc.
Contributions are welcome! To contribute:
- Fork this repository and create a new branch.
- Ensure your changes pass all tests and are synced with the main branch.
- For major changes, open an issue to discuss your proposal first.
- Submit a pull request with a clear description of your changes.
Clone the repository:
git clone https://github.com/LemonNoCry/SnowflakeId.AutoRegister.git
Navigate to the project directory:
cd SnowflakeId.AutoRegister
Restore dependencies:
dotnet restore
Build the project:
dotnet build
This project is licensed under the MIT License.