雪花算法-唯一ID生成器

demo:

  1 public class Snowflake
  2     {
  3         private static long machineId;//机器ID
  4         private static long datacenterId = 0L;//数据ID
  5         private static long sequence = 0L;//计数从零开始
  6 
  7         private static readonly long twepoch = 806083200000L; //唯一时间随机量
  8 
  9         private static readonly long machineIdBits = 5L; //机器码字节数
 10         private static readonly long datacenterIdBits = 5L;//数据字节数
 11         public static long maxMachineId = -1L ^ (-1L << (int)machineIdBits); //最大机器ID
 12         private static readonly long maxDatacenterId = -1L ^ (-1L << (int)datacenterIdBits);//最大数据ID
 13 
 14         private static readonly long sequenceBits = 12L; //计数器字节数,12个字节用来保存计数码        
 15         private static readonly long machineIdShift = sequenceBits; //机器码数据左移位数,就是后面计数器占用的位数
 16         private static readonly long datacenterIdShift = sequenceBits + machineIdBits;
 17         private static readonly long timestampLeftShift = sequenceBits + machineIdBits + datacenterIdBits; //时间戳左移动位数就是机器码+计数器总字节数+数据字节数
 18         public static long sequenceMask = -1L ^ (-1L << (int)sequenceBits); //一微秒内可以产生计数,如果达到该值则等到下一微妙在进行生成
 19         private static long lastTimestamp = -1L;//最后时间戳
 20 
 21         private static object syncRoot = new object();//加锁对象
 22         static Snowflake snowflake;
 23 
 24         public static Snowflake Instance()
 25         {
 26             if (snowflake == null)
 27                 snowflake = new Snowflake();
 28             return snowflake;
 29         }
 30 
 31         public Snowflake()
 32         {
 33             Snowflakes(0L, 0L);
 34         }
 35 
 36         public Snowflake(long machineId)
 37         {
 38             Snowflakes(machineId, -1);
 39         }
 40 
 41         public Snowflake(long machineId, long datacenterId)
 42         {
 43             Snowflakes(machineId, datacenterId);
 44         }
 45 
 46         private void Snowflakes(long machineId, long datacenterId)
 47         {
 48             if (machineId >= 0)
 49             {
 50                 if (machineId > maxMachineId)
 51                 {
 52                     throw new Exception("机器码ID非法");
 53                 }
 54                 Snowflake.machineId = machineId;
 55             }
 56             if (datacenterId >= 0)
 57             {
 58                 if (datacenterId > maxDatacenterId)
 59                 {
 60                     throw new Exception("数据中心ID非法");
 61                 }
 62                 Snowflake.datacenterId = datacenterId;
 63             }
 64         }
 65 
 66         /// <summary>
 67         /// 生成当前时间戳
 68         /// </summary>
 69         /// <returns>毫秒</returns>
 70         private static long GetTimestamp()
 71         {
 72             return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
 73         }
 74 
 75         /// <summary>
 76         /// 获取下一微秒时间戳
 77         /// </summary>
 78         /// <param name="lastTimestamp"></param>
 79         /// <returns></returns>
 80         private static long GetNextTimestamp(long lastTimestamp)
 81         {
 82             long timestamp = GetTimestamp();
 83             if (timestamp <= lastTimestamp)
 84             {
 85                 timestamp = GetTimestamp();
 86             }
 87             return timestamp;
 88         }
 89 
 90         /// <summary>
 91         /// 获取长整形的ID
 92         /// </summary>
 93         /// <returns></returns>
 94         public long GetId()
 95         {
 96             lock (syncRoot)
 97             {
 98                 long timestamp = GetTimestamp();
 99                 if (lastTimestamp == timestamp)
100                 { //同一微妙中生成ID
101                     sequence = (sequence + 1) & sequenceMask; //用&运算计算该微秒内产生的计数是否已经到达上限
102                     if (sequence == 0)
103                     {
104                         //一微妙内产生的ID计数已达上限,等待下一微妙
105                         timestamp = GetNextTimestamp(lastTimestamp);
106                     }
107                 }
108                 else
109                 {
110                     //不同微秒生成ID
111                     sequence = 0L;
112                 }
113                 if (timestamp < lastTimestamp)
114                 {
115                     throw new Exception("时间戳比上一次生成ID时时间戳还小,故异常");
116                 }
117                 lastTimestamp = timestamp; //把当前时间戳保存为最后生成ID的时间戳
118                 long Id = ((timestamp - twepoch) << (int)timestampLeftShift)
119                     | (datacenterId << (int)datacenterIdShift)
120                     | (machineId << (int)machineIdShift)
121                     | sequence;
122                 return Id;
123             }
124         }
125     }

 

posted @ 2020-08-12 16:44  一粒尘埃、  阅读(1436)  评论(0编辑  收藏  举报