.NET集成IdGenerator生成分布式全局唯一ID
warning:
这篇文章距离上次修改已过201天,其中的内容可能已经有所变动。
using System;
using System.Threading.Tasks;
using Surging.Core.CPlatform.Ioc;
using Surging.Core.CPlatform.Utilities;
namespace Surging.Core.Domain.Entities
{
public static class IdGenerator
{
static IdGenerator()
{
// 初始化时获取一次时间戳
_initStamp = GetTimeStamp();
}
// 获取当前时间的时间戳
private static long GetTimeStamp()
{
var time = DateTime.UtcNow;
var span = time - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
return (long)span.TotalMilliseconds;
}
// 记录程序启动时的时间戳
private static long _initStamp = GetTimeStamp();
// 获取下一个ID
public static async Task<string> GetId(int dataCenterId, int machineId)
{
// 确保dataCenterId和machineId在其相应范围内
if (dataCenterId < 0 || dataCenterId > 31)
throw new ArgumentException("dataCenterId should between 0 and 31");
if (machineId < 0 || machineId > 31)
throw new ArgumentException("machineId should between 0 and 31");
// 获取当前时间的时间戳
var timestamp = GetTimeStamp();
// 如果当前时间小于或等于上次ID生成时间,则等待直到时间改变
while (timestamp <= _lastTimestamp)
{
await Task.Delay(1);
timestamp = GetTimeStamp();
}
// 记录下次ID生成的时间戳
_lastTimestamp = timestamp;
// 移位并通过位运算生成ID的不同部分
var diff = timestamp - _initStamp;
var time = (diff % 0x1000) << 16;
var dataCenter = dataCenterId << 17;
var machine = machineId << 12;
var sequence = _sequence;
// 序列号增加并且通过位运算组合成最终的ID
_sequence = (sequence + 1) & 0xfff;
var id = (time | dataCenter | machine | sequence).ToString();
return id;
}
// 序列号
private static int _sequence = 0;
// 记录上次ID生成的时间戳
private static long _lastTimestamp = -1;
}
}
这个代码实例提供了一个简化版本的IdGenerator
类,用于生成分布式全局唯一ID。它使用了时间戳和序列号来生成ID,并且通过位运算组合这些元素。这个实现没有使用IdGenerator
类,而是直接提供了一个静态方法GetId
,用于生成ID。这个实现假设了dataCenterId和machineId已经在它们的有效范围内,并且没有提供参数验证的逻辑。这是为了保持代码的简洁,专注于ID生成逻辑。
评论已关闭