Delphi 雪花ID

2021/5/6 18:28:48

本文主要是介绍Delphi 雪花ID,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

RAD Studio 10.2.3 测试√


单元文件

unit uAlgorithm;

interface

uses
  Winapi.Windows, System.DateUtils, System.SysUtils;

type
  // 算法
  TAlgorithm = class

  end;

  // 雪花算法
  {
  雪花算法简单描述:
+ 最高位是符号位,始终为0,不可用。
+ 41位的时间序列,精确到毫秒级,41位的长度可以使用69年。时间位还有一个很重要的作用是可以根据时间进行排序。
+ 10位的机器标识,10位的长度最多支持部署1024个节点。
+ 12位的计数序列号,序列号即一系列的自增id,可以支持同一节点同一毫秒生成多个ID序号,12位的计数序列号支持每个节点每毫秒产生4096个ID序号。
  }
  TSnowflakeAlgorithm = class(TAlgorithm)
  private
    FCS: TRTLCriticalSection;    // 临界区
    FNowTime: Int64;             // 现在时间[单位: ms]
    FLastTime: Int64;            // 上个时间[单位: ms]
    FMachineID: Integer;         // 机器标识      0 .. 1023 [十进制 1023 = 二进制 1111111111   ]
    FCount: Integer;             // 计数序列号    0 .. 4095 [十进制 4095 = 二进制 111111111111 ]
  public
    constructor Create;
    destructor Destroy; override;
    function GetSnowflakeID: Int64;    // 获取雪花ID
  end;

var
  G_SnowflakeAlgorithm: TSnowflakeAlgorithm;

implementation

{ TSnowflakeAlgorithm }

constructor TSnowflakeAlgorithm.Create;
begin
  InitializeCriticalSection(FCS);      // 初始化临界区
  FMachineID := 999;                   // 固定的机器 ID
  FLastTime := MilliSecondsBetween(Now, EncodeDateTime(1970, 1, 1, 8, 0, 0, 0));
  FCount := 0;
end;

destructor TSnowflakeAlgorithm.Destroy;
begin
  DeleteCriticalSection(FCS);          // 删除临界区
  inherited;
end;

function TSnowflakeAlgorithm.GetSnowflakeID: Int64;
begin
  EnterCriticalSection(FCS);
  try
    FNowTime := MilliSecondsBetween(Now, EncodeDateTime(1970, 1, 1, 8, 0, 0, 0)); // 当前毫秒时间戳

    if FLastTime = FNowTime then  // 如果上一毫秒的时间 = 现在的时间
    begin
      if FCount > 4095 then     // 如果同一毫秒内生成的 ID 个数 > 4096
      begin
//        Sleep(1); // 等待下一毫秒再进行生成
        while FLastTime >= FNowTime do
        begin
          FNowTime := MilliSecondsBetween(Now, EncodeDateTime(1970, 1, 1, 8, 0, 0, 0));
        end;
        FLastTime := FNowTime; // 重新给上一毫秒时间 赋值
      end;
    end
    else
    begin
      FCount := 0; // 初始化计数
      FLastTime := FNowTime; // 重新给上一毫秒时间 赋值
    end;

    Result := (FNowTime shl 22) or (FMachineID shl 12) or FCount;
    Inc(FCount); // 对计数变量进行自增
  finally
    LeaveCriticalSection(FCS);
  end;
end;

end.

用法

procedure TForm1.Button_SnowflakeIDClick(Sender: TObject);
var
  i: Integer;
begin
  // 时间是从1970年1月1日8点到当前的间隔[单位: ms]
  Memo1.Lines.Add('当前时间戳: ' + IntToStr(MilliSecondsBetween(Now, EncodeDateTime(1970, 1, 1, 8, 0, 0, 0))));

  G_SnowflakeAlgorithm := TSnowflakeAlgorithm.Create;
  for i := 0 to 100 do
  begin
    Memo1.Lines.Add((G_SnowflakeAlgorithm.GetSnowflakeID).ToString);
  end;
  G_SnowflakeAlgorithm.Free;
end;

运行结果

在这里插入图片描述


一点点笔记,以便以后翻阅。



这篇关于Delphi 雪花ID的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!


扫一扫关注最新编程教程