namespace FoodLabeling.Th.Domain.Shared.Helpers; /// /// 雪花 Id 生成器(项目规范:实体 string Id 使用 NextId().ToString()) /// public static class YitIdHelper { private const long Epoch = 1_609_459_200_000L; private const int WorkerIdBits = 5; private const int SequenceBits = 12; private const long MaxSequence = (1L << SequenceBits) - 1; private const int WorkerIdShift = SequenceBits; private const int TimestampShift = SequenceBits + WorkerIdBits; private const long WorkerId = 1; private static long _lastTimestamp = -1L; private static long _sequence; private static readonly object SyncRoot = new(); /// /// 生成下一个雪花 Id /// public static long NextId() { lock (SyncRoot) { var timestamp = CurrentTimestamp(); if (timestamp < _lastTimestamp) { timestamp = WaitNextMillis(_lastTimestamp); } if (_lastTimestamp == timestamp) { _sequence = (_sequence + 1) & MaxSequence; if (_sequence == 0) { timestamp = WaitNextMillis(_lastTimestamp); } } else { _sequence = 0; } _lastTimestamp = timestamp; return ((timestamp - Epoch) << TimestampShift) | (WorkerId << WorkerIdShift) | _sequence; } } private static long CurrentTimestamp() => DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); private static long WaitNextMillis(long lastTimestamp) { var timestamp = CurrentTimestamp(); while (timestamp <= lastTimestamp) { timestamp = CurrentTimestamp(); } return timestamp; } }