C# 雪花Id(Snowflake ID)是一种分布式唯一标识生成算法,旨在解决分布式系统中生成唯一标识的需求。它是由Twitter公司提出的一种算法,在大规模分布式系统中广泛应用。
雪花Id的结构如下:
0 | 0000000000 | 00000 | 00000 | 000000000000
位数 | 时间戳(ms) | 数据中心ID | 工作节点ID | 自增序列号
具体说明如下:
-
0位:符号位,始终为0。
-
时间戳:用毫秒级的时间戳来表示自1970年1月1日 00:00:00 GMT以来的时间。
-
数据中心ID:用来区分不同的数据中心,可根据实际情况分配,最多可容纳32个数据中心。
-
工作节点ID:用来区分不同的工作节点,同样可以根据实际情况分配,最多可容纳32个工作节点。
-
自增序列号:在同一毫秒内自增,用于解决并发生成的问题,最多可容纳4096个ID。
通过这种结构,雪花Id可以在分布式系统中生成大约每秒数百万个不重复的、有序的唯一标识。
下面是一个C#实现雪花Id生成算法的例子:
public class SnowflakeIdGenerator
{
private long _lastTimestamp = 0; // 上一次生成的时间戳
private readonly int _dataCenterId; // 数据中心ID
private readonly int _workerId; // 工作节点ID
private long _sequence = 0; // 自增序列号
public SnowflakeIdGenerator(int dataCenterId, int workerId)
{
if (dataCenterId < 0 || dataCenterId > 31)
throw new ArgumentException("Data center ID must be between 0 and 31.");
if (workerId < 0 || workerId > 31)
throw new ArgumentException("Worker ID must be between 0 and 31.");
_dataCenterId = dataCenterId; // 初始化数据中心ID
_workerId = workerId; // 初始化工作节点ID
}
public long GenerateId()
{
long timestamp = GetTimestamp(); // 获取当前时间戳
if (timestamp < _lastTimestamp) // 如果当前时间戳小于上一次生成的时间戳
throw new Exception("Clock moved backwards. Refusing to generate ID.");
if (timestamp == _lastTimestamp) // 如果当前时间戳与上一次生成的时间戳相同
{
_sequence = (_sequence + 1) & 4095; // 自增序列号,并将其限制在0~4095之间
if (_sequence == 0)
timestamp = WaitNextMillis(_lastTimestamp); // 如果自增序列号达到上限,等待下一毫秒的时间戳
}
else
{
_sequence = 0; // 如果当前时间戳发生变化,重置自增序列号
}
_lastTimestamp = timestamp; // 更新上一次生成的时间戳
// 生成雪花Id,通过位运算将各个部分组合起来
return ((timestamp - 1580000000000L) << 22) // 时间戳部分(中间的 - 1580000000000L 是为了减少占用位数)
| (_dataCenterId << 17) // 数据中心ID部分
| (_workerId << 12) // 工作节点ID部分
| _sequence; // 自增序列号部分
}
private long GetTimestamp()
{
return DateTimeOffset.UtcNow.Ticks / 10000 - 62135596800000L; // 获取当前时间的毫秒级时间戳
}
private long WaitNextMillis(long lastTimestamp)
{
while (GetTimestamp() <= lastTimestamp) ; // 等待下一毫秒的时间戳
return GetTimestamp(); // 返回新的时间戳
}
}
// 使用雪花Id生成器
var generator = new SnowflakeIdGenerator(dataCenterId: 1, workerId: 2);
long id = generator.GenerateId();
Console.WriteLine(id);
这段代码实现了一个雪花Id生成器类SnowflakeIdGenerator,并使用它生成一个雪花Id,其中 dataCenterId
和 workerId
分别是数据中心和工作节点的标识,通过调用GenerateId方法可以生成一个雪花Id。该生成器依赖于数据中心ID和工作节点ID两个参数进行初始化。具体的生成过程是根据当前时间戳、数据中心ID、工作节点ID和自增序列号,通过位运算组合生成一个64位的唯一标识。请注意,该代码示例中的时间戳部分为了减少占用位数进行了处理,实际应用中可能需要根据需求进行调整。
在示例代码的最后,创建了一个雪花Id生成器对象并调用GenerateId方法生成一个雪花Id,并将其打印在控制台上。
注意,在实际使用中,需要根据不同的分布式环境配置合适的数据中心ID和工作节点ID,以保证生成的雪花Id的唯一性和顺序性。