YitIdHelper.cs
1.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
namespace FoodLabeling.Th.Domain.Shared.Helpers;
/// <summary>
/// 雪花 Id 生成器(项目规范:实体 string Id 使用 NextId().ToString())
/// </summary>
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();
/// <summary>
/// 生成下一个雪花 Id
/// </summary>
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;
}
}