-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathSnowflake.pas
169 lines (144 loc) · 3.6 KB
/
Snowflake.pas
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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
unit Snowflake;
interface
uses
SysUtils, SyncObjs, DateUtils;
type
TSnowflake = class
private
FOrgID: Integer; //机构号
FMachineID: integer; //机器号
FLocker: TCriticalSection;
fTime: Int64; //时间戳
fsn: int64; //序列
public
constructor Create;
destructor Destroy; override;
property MachineID: Integer read FMachineID write FMachineID;
property OrgID: Integer read FOrgID write FOrgID;
function Generate: Int64;
end;
implementation
const
Epoch: int64 = 1539615188000; //北京时间2018-10-15号 curtime := DateTimeToUnix(Now) * 1000;
OrgBits: Byte = 5; //机构号 0..31
MachineBits: Byte = 5; //机器号 0..31
snBits: Byte = 12; //序列号12位
timeShift: Byte = 22; //时间戳左移位数=序列号位数+机器号位数+机构号位数
orgShift: Byte = 17; //机构号左移位数=序列号位数+机器号位数
machineShift: Byte = 12; //工作站左移位数=序列号位数
snMask: Word = 4095; //12位的计数序列号支持每个节点每毫秒产生4096个ID序号
{ TSnowflake }
constructor TSnowflake.Create;
begin
FLocker := TCriticalSection.Create;
end;
destructor TSnowflake.Destroy;
begin
FLocker.Free;
inherited;
end;
function TSnowflake.Generate: Int64;
var
curtime: Int64;
begin
FLocker.Acquire;
try
curtime := DateTimeToUnix(Now) * 1000;
if curtime = fTime then
begin
fsn := (fsn + 1) and snMask;
if fsn = 0 then
begin
while curtime <= fTime do
curtime := DateTimeToUnix(Now) * 1000;
end;
end
else
fsn := 0;
fTime := curtime;
Result := (curtime - Epoch) shl timeShift
or FOrgID shl orgShift
or FMachineID shl machineShift
or fsn;
finally
FLocker.Release;
end;
end;
initialization
end.
interface
uses
SysUtils, SyncObjs, DateUtils;
type
TSnowflake = class
private
FMachineID: integer; //机器号
FLocker: TCriticalSection;
fTime: Int64; //时间戳
fsn: int64; //序列
public
constructor Create;
destructor Destroy; override;
property MachineID: Integer read FMachineID write FMachineID;
function Generate: Int64;
end;
implementation
const
Epoch: int64 = 1539615188000; //北京时间2018-10-15号
MachineBits: Byte = 10; //机器号10位 0..1023
snBits: Byte = 12; //序列号12位
timeShift: Byte = 22; //时间戳左移位数=序列号12位+机器号10位
machineShift: Byte = 12; //工作站左移位数
snMask: Word = 4095; //12位的计数序列号支持每个节点每毫秒产生4096个ID序号
{ TSnowflake }
constructor TSnowflake.Create;
begin
FLocker := TCriticalSection.Create;
end;
destructor TSnowflake.Destroy;
begin
FLocker.Free;
inherited;
end;
function TSnowflake.Generate: Int64;
var
curtime: Int64;
begin
FLocker.Acquire;
try
curtime := DateTimeToUnix(Now) * 1000;
if curtime = fTime then
begin
fsn := (fsn + 1) and snMask;
if fsn = 0 then
begin
while curtime <= fTime do
curtime := DateTimeToUnix(Now) * 1000;
end;
end
else
fsn := 0;
fTime := curtime;
Result := (curtime - Epoch) shl timeShift or FMachineID shl machineShift or fsn;
finally
FLocker.Release;
end;
end;
initialization
end.
unit Snowflake;
{ 调用演示
procedure TForm1.Button1Click(Sender: TObject);
var s: TSnowflake;
i: Integer;
begin
s := TSnowflake.Create;
s.OrgID := 8;
s.MachineID :=10;
for i:=1 to 30 do
begin
Memo1.Lines.Add(IntToStr(s.Generate));
end;
s.Free;
end;
}