雪花算法(DELPHI实现)
雪花算法(DELPHI实现)
生成ID能够按照时间有序生成。
分布式系统内不会产生重复id(用workerId来做区分)。
自增ID:对于数据敏感场景不宜使用,且不适合于分布式场景。
GUID:采用无意义字符串,数据量增大时造成访问过慢,且不宜排序。
算法描述:
- 最高位是符号位,始终为0,不可用。
- 41位的时间序列,精确到毫秒级,41位的长度可以使用69年。时间位还有一个很重要的作用是可以根据时间进行排序。
- 10位的机器标识,10位的长度最多支持部署1024个节点。
- 12位的计数序列号,序列号即一系列的自增id,可以支持同一节点同一毫秒生成多个ID序号,12位的计数序列号支持每个节点每毫秒产生4096个ID序号。
在delphi7下面,测试通过。
下面的算法,适用于单机构生成不重复ID。
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 | 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:
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 | 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. |
演示效果:
本文来自博客园,作者:{咏南中间件},转载请注明原文链接:https://www.cnblogs.com/hnxxcxg/p/11143681.html
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
· [.NET]调用本地 Deepseek 模型
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· .NET Core 托管堆内存泄露/CPU异常的常见思路
· PostgreSQL 和 SQL Server 在统计信息维护中的关键差异
· DeepSeek “源神”启动!「GitHub 热点速览」
· 微软正式发布.NET 10 Preview 1:开启下一代开发框架新篇章
· 我与微信审核的“相爱相杀”看个人小程序副业
· C# 集成 DeepSeek 模型实现 AI 私有化(本地部署与 API 调用教程)
· spring官宣接入deepseek,真的太香了~
2014-07-06 咏南中间件及中间件集群解决方案