用户十二生肖 發表於 2019-7-6 18:37:00

雪花算法(DELPHI实现)

<p>雪花算法(DELPHI实现)</p>
<p>生成ID能够按照时间有序生成。</p>
<p>分布式系统内不会产生重复id(用workerId来做区分)。</p>
<p>自增ID:对于数据敏感场景不宜使用,且不适合于分布式场景。</p>
<p>GUID:采用无意义字符串,数据量增大时造成访问过慢,且不宜排序。</p>
<p><strong>算法描述:</strong></p>
<ul>
<li>最高位是符号位,始终为0,不可用。</li>
<li>41位的时间序列,精确到毫秒级,41位的长度可以使用69年。时间位还有一个很重要的作用是可以根据时间进行排序。</li>
<li>10位的机器标识,10位的长度最多支持部署1024个节点。</li>
<li>12位的计数序列号,序列号即一系列的自增id,可以支持同一节点同一毫秒生成多个ID序号,12位的计数序列号支持每个节点每毫秒产生4096个ID序号。</li>
</ul>
<p><img src="https://img2018.cnblogs.com/blog/368779/201907/368779-20190708095714142-1276562354.png"></p>
<p>在delphi7下面,测试通过。</p>
<p>下面的算法,适用于单机构生成不重复ID。</p>
<p>&nbsp;</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">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 &lt;= 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.
</pre>
</div>
<p> 下面的算法,适用于连锁机构生成分布式ID:</p>
<div class="cnblogs_Highlighter">
<pre class="brush:csharp;gutter:true;">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 &lt;= 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.
</pre>
</div>
<p>  </p>
<p> </p>
<p>&nbsp;</p>
<p>  演示效果:</p>
<p><img src="https://img2018.cnblogs.com/blog/368779/201907/368779-20190706183652513-840464133.png"></p>

</div>
<div id="MySignature" role="contentinfo">
    <p>本文来自博客园,作者:{咏南中间件},转载请注明原文链接:https://www.cnblogs.com/hnxxcxg/p/11143681.html</p><br><br>
来源:https://www.cnblogs.com/hnxxcxg/p/11143681.html
頁: [1]
查看完整版本: 雪花算法(DELPHI实现)