.net雪花算法

   public class Snowflake
   {
       private const int RegionIdBits = 2;
       private const int WorkerIdBits = 10;
       private const int SequenceBits = 11;

       private static readonly int MaxRegionId = (1 << RegionIdBits) - 1;     // 3
       private static readonly int MaxWorkerId = (1 << WorkerIdBits) - 1;    // 1023
       private static readonly long SequenceMask = (1L << SequenceBits) - 1; // 2047

       private static readonly int WorkerIdShift = SequenceBits;                      // 11
       private static readonly int RegionIdShift = SequenceBits + WorkerIdBits;     // 21
       private static readonly int TimestampLeftShift = SequenceBits + WorkerIdBits + RegionIdBits; // 23

       private readonly long _twepoch = 1400000000000L;
       private long _lastTimestamp = -1L;
       private long _sequence = 0L;
       private readonly int _workerId;
       private readonly int _regionId;
       private readonly Random _random = new Random();
       private readonly object _lock = new object();

       public Snowflake(int workerId, int regionId = 0)
       {
           if (workerId < 0 || workerId > MaxWorkerId)
               throw new ArgumentException($"WorkerId must be between 0 and {MaxWorkerId}");
           if (regionId < 0 || regionId > MaxRegionId)
               throw new ArgumentException($"RegionId must be between 0 and {MaxRegionId}");

           _workerId = workerId;
           _regionId = regionId;
       }

       public long Generate(int? busId = null)
       {
           bool isPadding = busId.HasValue;
           int paddingNum = isPadding ? busId.Value : _regionId;

           lock (_lock)
           {
               long timestamp = GetTime();

               if (timestamp < _lastTimestamp)
               {
                   long diff = _lastTimestamp - timestamp;
                   throw new InvalidOperationException(
                       $"Clock moved backwards. Refusing to generate id for {diff} milliseconds.");
               }

               if (timestamp == _lastTimestamp)
               {
                   _sequence = (_sequence + 1) & SequenceMask;
                   if (_sequence == 0)   // 当前毫秒内 sequence 用尽,等待下一毫秒
                   {
                       timestamp = TailNextMillis(_lastTimestamp);
                       // 关键修复:进入新毫秒后,sequence 应重新随机化(避免恒为 0)
                       _sequence = (long)_random.Next(0, (int)SequenceMask + 1);
                   }
               }
               else
               {
                   // 不同毫秒:随机初始化 sequence(范围 0~2047)
                   _sequence = (long)_random.Next(0, (int)SequenceMask + 1);
               }

               _lastTimestamp = timestamp;

               return ((timestamp - _twepoch) << TimestampLeftShift)
                      | ((long)paddingNum << RegionIdShift)
                      | ((long)_workerId << WorkerIdShift)
                      | _sequence;
           }
       }

       private long TailNextMillis(long lastTimestamp)
       {
           long timestamp = GetTime();
           while (timestamp <= lastTimestamp)
           {
               timestamp = GetTime();
           }
           return timestamp;
       }

       private static long GetTime() => DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
   }

   // 全局单例建议(例如在 DI 中注册为 Singleton)
   public static class SnowflakeSingleton
   {
       private static readonly Lazy<Snowflake> _instance = new Lazy<Snowflake>(() => new Snowflake(workerId: 0));
       public static Snowflake Instance => _instance.Value;
   }
            for (int i = 0; i < 100; i++)
            {
                Console.WriteLine(SnowflakeSingleton.Instance.Generate());
            }
            Console.Read();

 

posted @ 2026-05-26 17:41  江境纣州  阅读(6)  评论(0)    收藏  举报