自己动手实现snowflake.net

参考学习自 https://www.cnblogs.com/sunyuliang/p/12161416.html

  1 using System;
  2 
  3 namespace Common
  4 {
  5     public interface IIdGenerator
  6     {
  7         public long NextId();
  8         public DateTime ToUtcTime(long id);
  9     }
 10 
 11     /// <summary>
 12     /// (Timestamp - Twepoch) << 22 | WorkerId << 12 | Sequence
 13     /// </summary>
 14     public class IdGenerator : IIdGenerator
 15     {
 16         /// <summary>
 17         /// default 1577836800000L
 18         /// </summary>
 19         private readonly long _twepoch;
 20         public readonly long _workerId;
 21         private long _sequence;
 22         private long _lastTimestamp;
 23 
 24         public readonly DateTime DefaultEpoch = new DateTime(2020, 1, 1, 0, 0, 0, DateTimeKind.Utc);
 25         public readonly DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
 26         private const int _workerIdBits = 10;
 27         private const int _sequenceBits = 12;
 28         private const long _minWorkerId = 1L;
 29         private const long _maxWorkerId = -1L ^ (-1L << _workerIdBits);
 30         private const long _maxSequence = -1L ^ (-1L << _sequenceBits);
 31         private const int _workerIdShift = _sequenceBits;
 32         private const int _timestampLeftShift = _sequenceBits + _workerIdBits;
 33 
 34         /// <summary>
 35         /// 
 36         /// </summary>
 37         /// <param name="workerId">1~1023</param>
 38         public IdGenerator(object workerId)
 39         {
 40             if (workerId == null
 41                 || long.TryParse(workerId.ToString(), out _workerId) == false
 42                 || _workerId > _maxWorkerId
 43                 || _workerId < _minWorkerId)
 44             {
 45                 throw new Exception($"Worker Id mast between { _minWorkerId } and { _maxWorkerId } ");
 46             }
 47 
 48             _twepoch = (long)(DefaultEpoch - Jan1st1970).TotalMilliseconds;
 49             _sequence = 0L;
 50             _lastTimestamp = -1L;
 51         }
 52 
 53         public long NextId()
 54         {
 55             lock (this)
 56             {
 57                 var timestamp = GetCurrentTimestamp();
 58                 timestamp = ++_sequence >= _maxSequence || timestamp < _lastTimestamp
 59                             ? GetNextTimestamp(_lastTimestamp)
 60                             : timestamp;
 61 
 62                 _sequence = timestamp > _lastTimestamp
 63                             ? 0L
 64                             : _sequence;
 65 
 66                 _lastTimestamp = timestamp;
 67 
 68                 var id = ((timestamp - _twepoch) << _timestampLeftShift)
 69                         | (_workerId << _workerIdShift)
 70                         | (_sequence);
 71                 return id;
 72             }
 73         }
 74 
 75         public DateTime ToUtcTime(long id)
 76         {
 77             var timestamp = (id >> _timestampLeftShift) + _twepoch;
 78             var datetime = Jan1st1970.AddMilliseconds(timestamp);
 79             return datetime;
 80         }
 81 
 82         private long GetNextTimestamp(long lastTimestamp)
 83         {
 84             var timestamp = GetCurrentTimestamp();
 85             if (lastTimestamp - timestamp > 1 * 1000)
 86             {
 87                 throw new Exception($"Clock moved backwards more than 1 seconds, last timestamp is { Jan1st1970.AddMilliseconds(lastTimestamp).ToString("o") }");
 88             }
 89             while (timestamp <= lastTimestamp)
 90             {
 91                 timestamp = GetCurrentTimestamp();
 92             }
 93             return timestamp;
 94         }
 95 
 96         private long GetCurrentTimestamp()
 97         {
 98             return (long)(DateTime.UtcNow - Jan1st1970).TotalMilliseconds;
 99         }
100     }
101 }

猜你喜欢

转载自www.cnblogs.com/lludcmmcdull/p/12497792.html