.net core 雪花算法
雪花算法(Snowflake)是一种用于生成唯一ID的算法,适用于分布式系统。在.NET Core中,你可以使用以下代码实现雪花算法生成ID:
public class SnowflakeIdGenerator
{
private const ulong Twepoch = 1288834974657; // 起始时间 (2010-11-04 09:42:54.657)
private const int WorkerIdBits = 5; // 机器ID所占的位数
private const int DatacenterIdBits = 5; // 数据中心ID所占的位数
private const int SequenceBits = 12; // 序列所占的位数
private const int WorkerIdShift = SequenceBits; // 机器ID左移位数,10位
private const int DatacenterIdShift = SequenceBits + WorkerIdBits; // 数据中心ID左移位数,15位
private const ulong TimestampLeftShift = SequenceBits + WorkerIdBits + DatacenterIdBits; // 时间戳左移位数,22位
private const ulong SequenceMask = -1 ^ (-1 << SequenceBits); // 生成序列的掩码,0000 0000 0000 0000 0000 0000 1111 1111 1111
private ulong _lastTimestamp = 0;
private ulong _sequence = 0;
private readonly object _lock = new object();
private readonly ulong _workerId; // 机器ID
private readonly ulong _datacenterId; // 数据中心ID
public SnowflakeIdGenerator(ulong workerId, ulong datacenterId)
{
_workerId = workerId;
_datacenterId = datacenterId;
}
public ulong NextId()
{
lock (_lock)
{
ulong timestamp = TimeGen();
if (_lastTimestamp > timestamp)
{
throw new Exception($"Clock moved backwards, refusing to generate id for {_lastTimestamp - timestamp} milliseconds");
}
if (_lastTimestamp == timestamp)
{
_sequence = (_sequence + 1) & SequenceMask;
if (_sequence == 0)
{
timestamp = TillNextMillis(_lastTimestamp);
}
}
else
{
_sequence = 0;
}
_lastTimestamp = timestamp;
ulong id = ((timestamp - Twepoch) << TimestampLeftShift) |
(_datacenterId << DatacenterIdShift) |
(_workerId << WorkerIdShift) | _sequence;
return id;
}
}
private ulong TimeGen()
{
return (ulong)(DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() - Twepoch);
}
private ulong TillNextMillis(ulong lastTimestamp)
{
ulong timestamp = TimeGen();
while (timestamp <= lastTimestamp)
{
timestamp = TimeGen();
}
return timestamp;
}
}
使用方法:
var idGenerator = new SnowflakeIdGenerator(workerId: 1, datacenterId: 1); // 设置机器ID和数据中心ID
ulong id = idGenerator.NextId(); // 生成新的ID
请根据实际情况设置workerId和datacenterId。这个实现是线程安全的,可以在分布式系统中使用。