雪花算法-唯一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     }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM