SnowFlake.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. using Masuit.Tools.DateTimeExt;
  2. using Masuit.Tools.Strings;
  3. using System;
  4. namespace Masuit.Tools.Systems
  5. {
  6. /// <summary>
  7. /// 动态生产有规律的分布式ID
  8. /// </summary>
  9. public class SnowFlake
  10. {
  11. #region 私有字段
  12. private static long _machineId; //机器码
  13. private static long _datacenterId; //数据ID
  14. private static long _sequence; //计数从零开始
  15. private static long _lastTimestamp = -1L; //最后时间戳
  16. private const long Twepoch = 687888001020L; //唯一时间随机量
  17. private const long MachineIdBits = 5L; //机器码字节数
  18. private const long DatacenterIdBits = 5L; //数据字节数
  19. private const long MaxMachineId = -1L ^ -1L << (int)MachineIdBits; //最大机器码
  20. private const long MaxDatacenterId = -1L ^ (-1L << (int)DatacenterIdBits); //最大数据ID
  21. private const long SequenceBits = 12L; //计数器字节数,12个字节用来保存计数码
  22. private const long MachineIdShift = SequenceBits; //机器码数据左移位数,就是后面计数器占用的位数
  23. private const long DatacenterIdShift = SequenceBits + MachineIdBits;
  24. private const long TimestampLeftShift = DatacenterIdShift + DatacenterIdBits; //时间戳左移动位数就是机器码+计数器总字节数+数据字节数
  25. private const long SequenceMask = -1L ^ -1L << (int)SequenceBits; //一毫秒内可以产生计数,如果达到该值则等到下一毫秒在进行生成
  26. private static readonly object SyncRoot = new object(); //加锁对象
  27. private static readonly NumberFormater NumberFormater = new NumberFormater(36);
  28. private static SnowFlake _snowFlake;
  29. #endregion
  30. /// <summary>
  31. /// 获取一个新的id
  32. /// </summary>
  33. public static string NewId => _snowFlake.GetUniqueId();
  34. /// <summary>
  35. /// 创建一个实例
  36. /// </summary>
  37. /// <returns></returns>
  38. public static SnowFlake GetInstance()
  39. {
  40. return _snowFlake ?? (_snowFlake = new SnowFlake());
  41. }
  42. /// <summary>
  43. /// 默认构造函数
  44. /// </summary>
  45. public SnowFlake()
  46. {
  47. Snowflakes(0, -1);
  48. }
  49. /// <summary>
  50. /// 构造函数
  51. /// </summary>
  52. /// <param name="machineId">机器码</param>
  53. public SnowFlake(long machineId)
  54. {
  55. Snowflakes(machineId, -1);
  56. }
  57. /// <summary>
  58. /// 构造函数
  59. /// </summary>
  60. /// <param name="machineId">机器码</param>
  61. /// <param name="datacenterId">数据中心id</param>
  62. public SnowFlake(long machineId, long datacenterId)
  63. {
  64. Snowflakes(machineId, datacenterId);
  65. }
  66. private void Snowflakes(long machineId, long datacenterId)
  67. {
  68. if (machineId >= 0)
  69. {
  70. if (machineId > MaxMachineId)
  71. {
  72. throw new Exception("机器码ID非法");
  73. }
  74. _machineId = machineId;
  75. }
  76. if (datacenterId >= 0)
  77. {
  78. if (datacenterId > MaxDatacenterId)
  79. {
  80. throw new Exception("数据中心ID非法");
  81. }
  82. _datacenterId = datacenterId;
  83. }
  84. }
  85. /// <summary>
  86. /// 获取长整形的ID
  87. /// </summary>
  88. /// <returns></returns>
  89. public long GetLongId()
  90. {
  91. lock (SyncRoot)
  92. {
  93. var timestamp = (long)DateTime.UtcNow.GetTotalMilliseconds();
  94. if (_lastTimestamp == timestamp)
  95. {
  96. //同一毫秒中生成ID
  97. _sequence = (_sequence + 1) & SequenceMask; //用&运算计算该毫秒内产生的计数是否已经到达上限
  98. if (_sequence == 0)
  99. {
  100. //一毫秒内产生的ID计数已达上限,等待下一毫秒
  101. timestamp = (long)DateTime.UtcNow.GetTotalMilliseconds();
  102. }
  103. }
  104. else
  105. {
  106. //不同毫秒生成ID
  107. _sequence = 0L;
  108. }
  109. _lastTimestamp = timestamp; //把当前时间戳保存为最后生成ID的时间戳
  110. long id = ((timestamp - Twepoch) << (int)TimestampLeftShift) | (_datacenterId << (int)DatacenterIdShift) | (_machineId << (int)MachineIdShift) | _sequence;
  111. return id;
  112. }
  113. }
  114. /// <summary>
  115. /// 获取一个字符串表示形式的id
  116. /// </summary>
  117. /// <returns></returns>
  118. public string GetUniqueId()
  119. {
  120. return NumberFormater.ToString(GetLongId());
  121. }
  122. /// <summary>
  123. /// 获取一个字符串表示形式的id
  124. /// </summary>
  125. /// <param name="maxLength">最大长度,至少6位</param>
  126. /// <returns></returns>
  127. public string GetUniqueShortId(int maxLength = 8)
  128. {
  129. if (maxLength < 6)
  130. {
  131. throw new ArgumentException("最大长度至少需要6位");
  132. }
  133. string id = GetUniqueId();
  134. int index = id.Length - maxLength;
  135. if (index < 0)
  136. {
  137. index = 0;
  138. }
  139. return id.Substring(index);
  140. }
  141. }
  142. }