using Masuit.Tools.DateTimeExt; using Masuit.Tools.Strings; using System; using System.Linq; using System.Net.NetworkInformation; using Masuit.Tools.Hardware; using System.Collections.Generic; using System.Net.Sockets; namespace Masuit.Tools.Systems { /// /// 动态生产有规律的分布式ID /// public class SnowFlake { #region 私有字段 private static long _offset; //起始偏移量 private static long _machineId; //机器码 private static long _sequence; //计数从零开始 private static long _lastTimestamp = -1L; //最后时间戳 private const long Twepoch = 687888001020L; //唯一时间随机量 private const int MachineBits = 10; //机器码字节数 private const int SequenceBits = 12; //计数器字节数,12个字节用来保存计数码 private const int MachineLeft = SequenceBits; //机器码数据左移位数,就是后面计数器占用的位数 private const long TimestampLeft = MachineBits + SequenceBits; //时间戳左移动位数就是机器码+计数器总字节数+数据字节数 private const long SequenceMask = -1L ^ -1L << SequenceBits; //一毫秒内可以产生计数,如果达到该值则等到下一毫秒在进行生成 private static readonly object SyncRoot = new(); //加锁对象 private static NumberFormater _numberFormater = new(36); private static SnowFlake _snowFlake; #endregion 私有字段 /// /// 获取一个新的id /// public static string NewId => GetInstance().GetUniqueId(); /// /// 获取一个新的id /// public static long LongId => GetInstance().GetLongId(); /// /// 创建一个实例 /// /// public static SnowFlake GetInstance() { return _snowFlake ??= new SnowFlake(); } /// /// 默认构造函数 /// public SnowFlake() { } /// /// 默认构造函数 /// static SnowFlake() { try { var mac = SystemInfo.GetMacAddress().FirstOrDefault(a => a.GetAddressBytes().Length > 0); if (mac != null) { var bytes = mac.GetAddressBytes(); SetMachienId(bytes[4] << 2 | bytes[5]); } else { var ip = SystemInfo.GetLocalUsedIP(); if (ip != null) { var bytes = ip.GetAddressBytes(); SetMachienId(bytes[3]); } } } catch { SetMachienId(0); } } /// /// 构造函数 /// /// 机器码 public SnowFlake(long machineId) { SetMachienId(machineId); } public static void SetMachienId(long machineId) { if (machineId >= 0) { if (machineId > 1024) { throw new Exception("机器码ID非法"); } _machineId = machineId; } } /// /// 设置数制格式化器 /// /// public static void SetNumberFormater(NumberFormater nf) { _numberFormater = nf; } /// /// 设置起始偏移量 /// /// public static void SetInitialOffset(long offset) { _offset = offset; } /// /// 获取长整形的ID /// /// public long GetLongId() { lock (SyncRoot) { var timestamp = DateTime.UtcNow.GetTotalMilliseconds(); if (_lastTimestamp == timestamp) { //同一毫秒中生成ID _sequence = (_sequence + 1) & SequenceMask; //用&运算计算该毫秒内产生的计数是否已经到达上限 if (_sequence == 0) { //一毫秒内产生的ID计数已达上限,等待下一毫秒 timestamp = DateTime.UtcNow.GetTotalMilliseconds(); } } else { //不同毫秒生成ID _sequence = 0L; } _lastTimestamp = timestamp; //把当前时间戳保存为最后生成ID的时间戳 long id = ((timestamp - Twepoch) << (int)TimestampLeft) | (_machineId << MachineLeft) | _sequence; return id - _offset; } } /// /// 获取一个字符串表示形式的id /// /// public string GetUniqueId() { return _numberFormater.ToString(GetLongId()); } /// /// 获取一个字符串表示形式的id /// /// 最大长度,至少6位 /// public string GetUniqueShortId(int maxLength = 8) { if (maxLength < 6) { throw new ArgumentException("最大长度至少需要6位"); } string id = GetUniqueId(); int index = id.Length - maxLength; if (index < 0) { index = 0; } return id.Substring(index); } } }