using System; using System.Threading; namespace StandardScene.CommonTools { public sealed class SnowflakeIdGenerator { // 默认起始时间戳:2026-01-01T00:00:00.000Z(Unix 毫秒) // 如果你希望生成的数字更短,可以在构造函数里传入更“近”的 _epochMs(建议全系统统一)。 private const long DefaultEpochMs = 1767225600000L; private const int WorkerIdBits = 5; // 机器ID所占的位数 private const int DatacenterIdBits = 5; // 数据中心ID所占的位数 private const int MaxWorkerId = -1 ^ (-1 << WorkerIdBits); // 最大机器ID private const int MaxDatacenterId = -1 ^ (-1 << DatacenterIdBits); // 最大数据中心ID private const int SequenceBits = 12; // 序列号所占的位数 private const int WorkerIdShift = SequenceBits; // 机器ID左移的位数 private const int DatacenterIdShift = SequenceBits + WorkerIdBits; // 数据中心ID左移的位数 private const int TimestampLeftShift = SequenceBits + WorkerIdBits + DatacenterIdBits; // 时间戳左移的位数 private const long SequenceMask = -1L ^ (-1L << SequenceBits); // 序列号的最大值 private const string Base62Alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; private readonly object _syncRoot = new object(); private readonly long _epochMs; private readonly long _workerId; // 机器ID private readonly long _datacenterId; // 数据中心ID private long _sequence; // 序列号 private long _lastTimestamp = -1L; // 上次生成ID的时间戳 public SnowflakeIdGenerator(long workerId, long datacenterId, long? epochMs = null) { this._epochMs = epochMs ?? DefaultEpochMs; if (this._epochMs > TimeGen()) { throw new ArgumentException("_epochMs cannot be in the future."); } if (workerId is > MaxWorkerId or < 0) { throw new ArgumentException($"worker Id can't be greater than {MaxWorkerId} or less than 0"); } if (datacenterId is > MaxDatacenterId or < 0) { throw new ArgumentException($"{datacenterId} can't be greater than {MaxDatacenterId} or less than 0"); } this._workerId = workerId; this._datacenterId = datacenterId; } public long NextId() { lock (_syncRoot) { long timestamp = TimeGen(); if (timestamp < _lastTimestamp) { // 容忍系统时钟回拨:等待到追上 _lastTimestamp,避免直接抛异常把业务打崩。 timestamp = TilNextMillis(_lastTimestamp); } if (_lastTimestamp == timestamp) { _sequence = (_sequence + 1) & SequenceMask; if (_sequence == 0) { timestamp = TilNextMillis(_lastTimestamp); } } else { _sequence = 0; } _lastTimestamp = timestamp; long id = ((timestamp - _epochMs) << TimestampLeftShift) | (_datacenterId << DatacenterIdShift) | (_workerId << WorkerIdShift) | _sequence; return id; } } /// /// 生成更短的字符串形式 ID(Base62 编码),便于显示/存储。 /// public string NextIdBase62() { ulong value = unchecked((ulong)NextId()); return ToBase62(value); } private static long TilNextMillis(long lastTimestamp) { var spin = new SpinWait(); long timestamp; do { spin.SpinOnce(); timestamp = TimeGen(); } while (timestamp <= lastTimestamp); return timestamp; } private static long TimeGen() { return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); } private static string ToBase62(ulong value) { if (value == 0) { return "0"; } // 2^64-1 的 base62 最大长度为 11(因为 62^11 > 2^64)。 char[] buffer = new char[11]; int pos = buffer.Length; while (value > 0) { ulong rem = value % 62; value /= 62; buffer[--pos] = Base62Alphabet[(int)rem]; } return new string(buffer, pos, buffer.Length - pos); } } }