雪花算法(DELPHI實現)
生成ID能夠按照時間有序生成。
分布式系統內不會產生重復id(用workerId來做區分)。
自增ID:對於數據敏感場景不宜使用,且不適合於分布式場景。
GUID:采用無意義字符串,數據量增大時造成訪問過慢,且不宜排序。
算法描述:
- 最高位是符號位,始終為0,不可用。
- 41位的時間序列,精確到毫秒級,41位的長度可以使用69年。時間位還有一個很重要的作用是可以根據時間進行排序。
- 10位的機器標識,10位的長度最多支持部署1024個節點。
- 12位的計數序列號,序列號即一系列的自增id,可以支持同一節點同一毫秒生成多個ID序號,12位的計數序列號支持每個節點每毫秒產生4096個ID序號。

在delphi7下面,測試通過。
下面的算法,適用於單機構生成不重復ID。
unit Snowflake;
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.
下面的算法,適用於連鎖機構生成分布式ID:
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;
}
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.
演示效果:

