using System; using System.Linq; namespace QYZH.InteractiveMagazine.Common.Helpers { /// /// 雪花ID生成器 /// 基于Twitter Snowflake算法实现 /// public static class SnowflakeIdHelper { private static long _sequence = 0L; private static long _lastTimestamp = -1L; private static readonly object _lock = new object(); // 基础时间戳 (2020-01-01 00:00:00 UTC) private const long TwEpoch = 1577836800000L; // 机器ID位数 private const int WorkerIdBits = 5; // 数据中心ID位数 private const int DataCenterIdBits = 5; // 序列号位数 private const int SequenceBits = 12; // 最大值计算 private const long MaxWorkerId = -1L ^ (-1L << WorkerIdBits); private const long MaxDataCenterId = -1L ^ (-1L << DataCenterIdBits); private const long MaxSequence = -1L ^ (-1L << SequenceBits); // 位移偏移量 private const int WorkerIdShift = SequenceBits; private const int DataCenterIdShift = SequenceBits + WorkerIdBits; private const int TimestampLeftShift = SequenceBits + WorkerIdBits + DataCenterIdBits; private static long _workerId; private static long _dataCenterId; /// /// 静态构造函数,初始化机器ID和数据中心ID /// static SnowflakeIdHelper() { _workerId = GetWorkerId(); _dataCenterId = GetDataCenterId(); } /// /// 初始化雪花ID生成器 /// /// 机器ID (0-31) /// 数据中心ID (0-31) public static void Initialize(long workerId, long dataCenterId) { if (workerId < 0 || workerId > MaxWorkerId) { throw new ArgumentException($"机器ID必须在0-{MaxWorkerId}范围内", nameof(workerId)); } if (dataCenterId < 0 || dataCenterId > MaxDataCenterId) { throw new ArgumentException($"数据中心ID必须在0-{MaxDataCenterId}范围内", nameof(dataCenterId)); } _workerId = workerId; _dataCenterId = dataCenterId; } /// /// 生成雪花ID /// /// 唯一的雪花ID public static long GenerateId() { lock (_lock) { long timestamp = GetCurrentMilliseconds(); // 时钟回拨检测 if (timestamp < _lastTimestamp) { throw new InvalidOperationException("时钟回拨异常,拒绝生成ID"); } // 同一毫秒内,序列号递增 if (timestamp == _lastTimestamp) { _sequence = (_sequence + 1) & MaxSequence; // 序列号溢出,等待下一毫秒 if (_sequence == 0) { timestamp = WaitNextMillis(_lastTimestamp); } } else { _sequence = 0L; } _lastTimestamp = timestamp; // 组装ID: 时间戳 + 数据中心ID + 机器ID + 序列号 return ((timestamp - TwEpoch) << TimestampLeftShift) | (_dataCenterId << DataCenterIdShift) | (_workerId << WorkerIdShift) | _sequence; } } /// /// 获取当前毫秒数 /// private static long GetCurrentMilliseconds() { return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); } /// /// 等待下一毫秒 /// private static long WaitNextMillis(long lastTimestamp) { long timestamp = GetCurrentMilliseconds(); while (timestamp <= lastTimestamp) { timestamp = GetCurrentMilliseconds(); } return timestamp; } /// /// 获取机器ID(基于MAC地址简单计算) /// private static long GetWorkerId() { try { string macAddress = System.Net.NetworkInformation.NetworkInterface.GetAllNetworkInterfaces() .FirstOrDefault(n => n.OperationalStatus == System.Net.NetworkInformation.OperationalStatus.Up && n.NetworkInterfaceType != System.Net.NetworkInformation.NetworkInterfaceType.Loopback)? .GetPhysicalAddress().ToString() ?? "0"; long hash = 0; foreach (char c in macAddress) { hash = (hash * 31 + c) & MaxWorkerId; } return hash; } catch { return 1; } } /// /// 获取数据中心ID(基于机器名简单计算) /// private static long GetDataCenterId() { try { string machineName = Environment.MachineName; long hash = 0; foreach (char c in machineName) { hash = (hash * 31 + c) & MaxDataCenterId; } return hash; } catch { return 1; } } } }