Snowflake 算法是 Twitter 开源的一种分布式 ID 生成策略,它可以在不依赖数据库或其他存储设备的情况下生成全局唯一的 ID。Snowflake 算法的 ID 结构包括时间戳、数据中心 ID、机器 ID 和序列号等部分。
以下是一个简单的 C# 实现 Snowflake 算法的示例代码:
using System;
using System.Threading;
public class Snowflake
{
private const long Twepoch = 1288834974657L;
private const int WorkerIdBits = 5;
private const int DatacenterIdBits = 5;
private const int SequenceBits = 12;
private const long MaxWorkerId = -1L ^ (-1L<< WorkerIdBits);
private const long MaxDatacenterId = -1L ^ (-1L<< DatacenterIdBits);
private const int WorkerIdShift = SequenceBits;
private const int DatacenterIdShift = SequenceBits + WorkerIdBits;
private const int TimestampLeftShift = SequenceBits + WorkerIdBits + DatacenterIdBits;
private const long SequenceMask = -1L ^ (-1L << SequenceBits);
private static long _sequence = 0L;
private static long _lastTimestamp = -1L;
private readonly long _workerId;
private readonly long _datacenterId;
private readonly object _lock = new object();
public Snowflake(long workerId, long datacenterId)
{
if (workerId > MaxWorkerId || workerId < 0)
{
throw new ArgumentException($"Worker Id can't be greater than {MaxWorkerId} or less than 0");
}
if (datacenterId > MaxDatacenterId || datacenterId < 0)
{
throw new ArgumentException($"Datacenter Id can't be greater than {MaxDatacenterId} or less than 0");
}
_workerId = workerId;
_datacenterId = datacenterId;
}
public long NextId()
{
lock (_lock)
{
var timestamp = GetCurrentTimestamp();
if (timestamp > _lastTimestamp)
{
_sequence = 0;
_lastTimestamp = timestamp;
}
else
{
_sequence = (_sequence + 1) & SequenceMask;
if (_sequence == 0)
{
timestamp = WaitNextMillis(_lastTimestamp);
_lastTimestamp = timestamp;
}
}
return ((timestamp - Twepoch)<< TimestampLeftShift) |
(_datacenterId<< DatacenterIdShift) |
(_workerId<< WorkerIdShift) |
_sequence;
}
}
private long GetCurrentTimestamp()
{
return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
}
private long WaitNextMillis(long lastTimestamp)
{
var timestamp = GetCurrentTimestamp();
while (timestamp <= lastTimestamp)
{
Thread.Sleep(1);
timestamp = GetCurrentTimestamp();
}
return timestamp;
}
}
这个实现中,我们定义了一个 Snowflake
类,它包含了 Twepoch
、WorkerIdBits
、DatacenterIdBits
、SequenceBits
等常量,用于计算 ID 的各个部分。同时,我们还定义了一些私有变量,如 _sequence
、_lastTimestamp
、_workerId
和 _datacenterId
,用于存储当前的序列号、最后一次生成 ID 的时间戳、工作节点 ID 和数据中心 ID。
Snowflake
类的构造函数接收两个参数,分别是工作节点 ID 和数据中心 ID,并进行合法性检查。NextId
方法用于生成下一个 ID,它首先获取当前的时间戳,然后根据时间戳、工作节点 ID、数据中心 ID 和序列号计算出一个新的 ID。如果当前时间戳小于上一次生成 ID 的时间戳,说明系统时钟回拨,此时需要等待下一毫秒再生成 ID。
GetCurrentTimestamp
方法用于获取当前的时间戳(毫秒级),WaitNextMillis
方法用于等待下一毫秒。
这个实现是线程安全的,因为我们使用了 lock
关键字来确保在生成 ID 时不会被其他线程打断。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
推荐阅读:C# Snowflake算法的适用范围