ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Delphi 雪花ID

2021-05-06 18:03:49  阅读:151  来源: 互联网

标签:begin end FLastTime Delphi TSnowflakeAlgorithm 雪花 毫秒 FNowTime 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;

运行结果

在这里插入图片描述


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

标签:begin,end,FLastTime,Delphi,TSnowflakeAlgorithm,雪花,毫秒,FNowTime,ID
来源: https://blog.csdn.net/qq_44111597/article/details/116459032

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有