C#雪花Id

C# 雪花Id(Snowflake ID)是一种分布式唯一标识生成算法,旨在解决分布式系统中生成唯一标识的需求。它是由Twitter公司提出的一种算法,在大规模分布式系统中广泛应用。

雪花Id的结构如下:

 0  |  0000000000  | 00000  |   00000     |    000000000000
 位数 |  时间戳(ms) |  数据中心ID |  工作节点ID  | 自增序列号

具体说明如下:

  1. 0位:符号位,始终为0。

  2. 时间戳:用毫秒级的时间戳来表示自1970年1月1日 00:00:00 GMT以来的时间。

  3. 数据中心ID:用来区分不同的数据中心,可根据实际情况分配,最多可容纳32个数据中心。

  4. 工作节点ID:用来区分不同的工作节点,同样可以根据实际情况分配,最多可容纳32个工作节点。

  5. 自增序列号:在同一毫秒内自增,用于解决并发生成的问题,最多可容纳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,其中 dataCenterIdworkerId 分别是数据中心和工作节点的标识,通过调用GenerateId方法可以生成一个雪花Id。该生成器依赖于数据中心ID和工作节点ID两个参数进行初始化。具体的生成过程是根据当前时间戳、数据中心ID、工作节点ID和自增序列号,通过位运算组合生成一个64位的唯一标识。请注意,该代码示例中的时间戳部分为了减少占用位数进行了处理,实际应用中可能需要根据需求进行调整。

在示例代码的最后,创建了一个雪花Id生成器对象并调用GenerateId方法生成一个雪花Id,并将其打印在控制台上。

注意,在实际使用中,需要根据不同的分布式环境配置合适的数据中心ID和工作节点ID,以保证生成的雪花Id的唯一性和顺序性。

你可能感兴趣的:(学习C#的笔记,c#,开发语言)