参考学习自 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 }