From 58d62507d4351302f0fb0314bb5cd4f6338c804c Mon Sep 17 00:00:00 2001 From: zhouzj Date: Sun, 28 Mar 2021 23:42:31 +0800 Subject: [PATCH] auto commit --- .gitignore | 258 +++++++++++++ C#.NET/README.md | 33 ++ C#.NET/source/.gitignore | 258 +++++++++++++ C#.NET/source/Yitter.IdGen.sln | 31 ++ C#.NET/source/Yitter.IdGenTest/GenTest.cs | 49 +++ C#.NET/source/Yitter.IdGenTest/Program.cs | 226 +++++++++++ .../Properties/launchSettings.json | 8 + .../Yitter.IdGenTest/Yitter.IdGenTest.csproj | 23 ++ .../Contract/IIdGenerator.cs | 29 ++ .../Contract/ISnowWorker.cs | 22 ++ .../Contract/IdGeneratorOptions.cs | 80 ++++ .../Contract/OverCostActionArg.cs | 57 +++ .../Yitter.IdGenerator/Core/SnowWorkerM1.cs | 350 ++++++++++++++++++ .../Yitter.IdGenerator/Core/SnowWorkerM2.cs | 58 +++ .../Yitter.IdGenerator/DefaultIdGenerator.cs | 100 +++++ .../source/Yitter.IdGenerator/YitIdHelper.cs | 53 +++ .../Yitter.IdGenerator.csproj | 29 ++ C/README.md | 8 + C/source/.gitignore | 258 +++++++++++++ C/source/CMakeLists.txt | 27 ++ C/source/YitIdHelper.c | 30 ++ C/source/YitIdHelper.h | 21 ++ C/source/idgen/CMakeLists.txt | 7 + C/source/idgen/IdGenOptions.c | 34 ++ C/source/idgen/IdGenOptions.h | 31 ++ C/source/idgen/IdGenerator.c | 107 ++++++ C/source/idgen/IdGenerator.h | 30 ++ C/source/idgen/SnowWorkerM1.c | 161 ++++++++ C/source/idgen/SnowWorkerM1.h | 53 +++ C/source/idgen/SnowWorkerM2.c | 30 ++ C/source/idgen/SnowWorkerM2.h | 13 + C/source/idgen/common.h | 15 + C/source/main.c | 67 ++++ Go/README.md | 29 ++ Go/source/contract/IIdGenerator.go | 11 + Go/source/contract/ISnowWorker.go | 11 + Go/source/contract/IdGeneratorException.go | 18 + Go/source/contract/IdGeneratorOptions.go | 31 ++ Go/source/contract/OverCostActionArg.go | 25 ++ Go/source/core/snowWorkerM1.go | 208 +++++++++++ Go/source/core/snowWorkerM2.go | 44 +++ Go/source/gen/DefaultIdGenerator.go | 75 ++++ Go/source/gen/YitIdHelper.go | 47 +++ Go/source/go.mod | 1 + Go/source/test/main.go | 36 ++ Java/README.md | 28 ++ Java/source/.gitignore | 25 ++ Java/source/LICENSE | 201 ++++++++++ Java/source/pom.xml | 93 +++++ .../com/yitter/contract/IIdGenerator.java | 9 + .../java/com/yitter/contract/ISnowWorker.java | 9 + .../yitter/contract/IdGeneratorException.java | 29 ++ .../yitter/contract/IdGeneratorOptions.java | 71 ++++ .../yitter/contract/OverCostActionArg.java | 51 +++ .../java/com/yitter/core/SnowWorkerM1.java | 261 +++++++++++++ .../java/com/yitter/core/SnowWorkerM2.java | 41 ++ .../com/yitter/idgen/DefaultIdGenerator.java | 79 ++++ .../java/com/yitter/idgen/YitIdHelper.java | 45 +++ .../main/java/com/yitter/test/GenTest.java | 38 ++ .../main/java/com/yitter/test/StartUp.java | 55 +++ PHP/README.md | 4 + README.en.md | 37 ++ README.md | 204 ++++++++++ Rust/README.md | 5 + Rust/source/.gitignore | 257 +++++++++++++ Rust/source/Cargo.lock | 98 +++++ Rust/source/Cargo.toml | 16 + Rust/source/src/lib.rs | 21 ++ Rust/source/src/main.rs | 53 +++ .../src/yitgen/contract/i_snow_worker.rs | 7 + .../yitgen/contract/id_generator_options.rs | 38 ++ Rust/source/src/yitgen/contract/mod.rs | 13 + .../yitgen/contract/over_cost_action_arg.rs | 12 + Rust/source/src/yitgen/core/mod.rs | 10 + Rust/source/src/yitgen/core/snow_worker_m1.rs | 269 ++++++++++++++ Rust/source/src/yitgen/core/snow_worker_m2.rs | 9 + .../src/yitgen/gen/default_id_generator.rs | 25 ++ Rust/source/src/yitgen/gen/mod.rs | 9 + Rust/source/src/yitgen/gen/yit_id_helper.rs | 42 +++ Rust/source/src/yitgen/mod.rs | 3 + ZeOthers/README.md | 7 + ZeOthers/Vlang/README.md | 4 + ZeOthers/Vlang/source/contract/IIdGenerator.v | 5 + ZeOthers/Vlang/source/contract/ISnowWorker.v | 5 + .../source/contract/IdGeneratorOptions.v | 13 + ZeOthers/Vlang/source/core/SnowWorkerM1.v | 198 ++++++++++ ZeOthers/Vlang/source/core/SnowWorkerM2.v | 38 ++ .../Vlang/source/gen/DefaultIdGenerator.v | 67 ++++ ZeOthers/Vlang/source/gen/YitIdHelper.v | 12 + ZeOthers/Vlang/source/test | Bin 0 -> 68456 bytes ZeOthers/Vlang/source/test.v | 31 ++ auto_commit.bat | 37 ++ auto_download.bat | 6 + tester/csharp_call_rust.png | Bin 0 -> 91699 bytes ...345\217\221(\345\276\252\347\216\257).png" | Bin 0 -> 102371 bytes ...4\345\220\210\346\265\213\350\257\225.png" | Bin 0 -> 23355 bytes 96 files changed, 5682 insertions(+) create mode 100644 .gitignore create mode 100644 C#.NET/README.md create mode 100644 C#.NET/source/.gitignore create mode 100644 C#.NET/source/Yitter.IdGen.sln create mode 100644 C#.NET/source/Yitter.IdGenTest/GenTest.cs create mode 100644 C#.NET/source/Yitter.IdGenTest/Program.cs create mode 100644 C#.NET/source/Yitter.IdGenTest/Properties/launchSettings.json create mode 100644 C#.NET/source/Yitter.IdGenTest/Yitter.IdGenTest.csproj create mode 100644 C#.NET/source/Yitter.IdGenerator/Contract/IIdGenerator.cs create mode 100644 C#.NET/source/Yitter.IdGenerator/Contract/ISnowWorker.cs create mode 100644 C#.NET/source/Yitter.IdGenerator/Contract/IdGeneratorOptions.cs create mode 100644 C#.NET/source/Yitter.IdGenerator/Contract/OverCostActionArg.cs create mode 100644 C#.NET/source/Yitter.IdGenerator/Core/SnowWorkerM1.cs create mode 100644 C#.NET/source/Yitter.IdGenerator/Core/SnowWorkerM2.cs create mode 100644 C#.NET/source/Yitter.IdGenerator/DefaultIdGenerator.cs create mode 100644 C#.NET/source/Yitter.IdGenerator/YitIdHelper.cs create mode 100644 C#.NET/source/Yitter.IdGenerator/Yitter.IdGenerator.csproj create mode 100644 C/README.md create mode 100644 C/source/.gitignore create mode 100644 C/source/CMakeLists.txt create mode 100644 C/source/YitIdHelper.c create mode 100644 C/source/YitIdHelper.h create mode 100644 C/source/idgen/CMakeLists.txt create mode 100644 C/source/idgen/IdGenOptions.c create mode 100644 C/source/idgen/IdGenOptions.h create mode 100644 C/source/idgen/IdGenerator.c create mode 100644 C/source/idgen/IdGenerator.h create mode 100644 C/source/idgen/SnowWorkerM1.c create mode 100644 C/source/idgen/SnowWorkerM1.h create mode 100644 C/source/idgen/SnowWorkerM2.c create mode 100644 C/source/idgen/SnowWorkerM2.h create mode 100644 C/source/idgen/common.h create mode 100644 C/source/main.c create mode 100644 Go/README.md create mode 100644 Go/source/contract/IIdGenerator.go create mode 100644 Go/source/contract/ISnowWorker.go create mode 100644 Go/source/contract/IdGeneratorException.go create mode 100644 Go/source/contract/IdGeneratorOptions.go create mode 100644 Go/source/contract/OverCostActionArg.go create mode 100644 Go/source/core/snowWorkerM1.go create mode 100644 Go/source/core/snowWorkerM2.go create mode 100644 Go/source/gen/DefaultIdGenerator.go create mode 100644 Go/source/gen/YitIdHelper.go create mode 100644 Go/source/go.mod create mode 100644 Go/source/test/main.go create mode 100644 Java/README.md create mode 100644 Java/source/.gitignore create mode 100644 Java/source/LICENSE create mode 100644 Java/source/pom.xml create mode 100644 Java/source/src/main/java/com/yitter/contract/IIdGenerator.java create mode 100644 Java/source/src/main/java/com/yitter/contract/ISnowWorker.java create mode 100644 Java/source/src/main/java/com/yitter/contract/IdGeneratorException.java create mode 100644 Java/source/src/main/java/com/yitter/contract/IdGeneratorOptions.java create mode 100644 Java/source/src/main/java/com/yitter/contract/OverCostActionArg.java create mode 100644 Java/source/src/main/java/com/yitter/core/SnowWorkerM1.java create mode 100644 Java/source/src/main/java/com/yitter/core/SnowWorkerM2.java create mode 100644 Java/source/src/main/java/com/yitter/idgen/DefaultIdGenerator.java create mode 100644 Java/source/src/main/java/com/yitter/idgen/YitIdHelper.java create mode 100644 Java/source/src/main/java/com/yitter/test/GenTest.java create mode 100644 Java/source/src/main/java/com/yitter/test/StartUp.java create mode 100644 PHP/README.md create mode 100644 README.en.md create mode 100644 README.md create mode 100644 Rust/README.md create mode 100644 Rust/source/.gitignore create mode 100644 Rust/source/Cargo.lock create mode 100644 Rust/source/Cargo.toml create mode 100644 Rust/source/src/lib.rs create mode 100644 Rust/source/src/main.rs create mode 100644 Rust/source/src/yitgen/contract/i_snow_worker.rs create mode 100644 Rust/source/src/yitgen/contract/id_generator_options.rs create mode 100644 Rust/source/src/yitgen/contract/mod.rs create mode 100644 Rust/source/src/yitgen/contract/over_cost_action_arg.rs create mode 100644 Rust/source/src/yitgen/core/mod.rs create mode 100644 Rust/source/src/yitgen/core/snow_worker_m1.rs create mode 100644 Rust/source/src/yitgen/core/snow_worker_m2.rs create mode 100644 Rust/source/src/yitgen/gen/default_id_generator.rs create mode 100644 Rust/source/src/yitgen/gen/mod.rs create mode 100644 Rust/source/src/yitgen/gen/yit_id_helper.rs create mode 100644 Rust/source/src/yitgen/mod.rs create mode 100644 ZeOthers/README.md create mode 100644 ZeOthers/Vlang/README.md create mode 100644 ZeOthers/Vlang/source/contract/IIdGenerator.v create mode 100644 ZeOthers/Vlang/source/contract/ISnowWorker.v create mode 100644 ZeOthers/Vlang/source/contract/IdGeneratorOptions.v create mode 100644 ZeOthers/Vlang/source/core/SnowWorkerM1.v create mode 100644 ZeOthers/Vlang/source/core/SnowWorkerM2.v create mode 100644 ZeOthers/Vlang/source/gen/DefaultIdGenerator.v create mode 100644 ZeOthers/Vlang/source/gen/YitIdHelper.v create mode 100644 ZeOthers/Vlang/source/test create mode 100644 ZeOthers/Vlang/source/test.v create mode 100644 auto_commit.bat create mode 100644 auto_download.bat create mode 100644 tester/csharp_call_rust.png create mode 100644 "tester/\346\257\217\346\254\2415W\345\271\266\345\217\221(\345\276\252\347\216\257).png" create mode 100644 "tester/\347\273\274\345\220\210\346\265\213\350\257\225.png" diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1e8572c --- /dev/null +++ b/.gitignore @@ -0,0 +1,258 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates +*.editorconfig + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +**/.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +*.snupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + + +# macOS +.DS_Store diff --git a/C#.NET/README.md b/C#.NET/README.md new file mode 100644 index 0000000..007bea0 --- /dev/null +++ b/C#.NET/README.md @@ -0,0 +1,33 @@ + +## 运行环境 + +.NET Standard 2.0+ + +## 引用nuget包 +``` + +``` + +## 调用示例 +``` +// 全局初始化设置WorkerId,默认最大2^16-1。(初始化过程全局只需一次,且必须最先设置) +var options = new IdGeneratorOptions(){ WorkerId = 1}; +YitIdHelper.SetIdGenerator(options); + +// 初始化以后,就可以在需要的地方调用方法生成ID。 +var newId = YitIdHelper.NextId(); + +``` +如果基于DI框架集成,可以参考 YitIdHelper 去管理 IdGenerator 对象,必须使用**单例**模式。 + +## options 默认值及说明 + +参考源码:/Contract/IdGeneratorOptions.cs + +## 事件说明 + +1.IIdGenerator.GenIdActionAsync 是一个可以向外部系统异步发送ID生成消息的事件,它包含的消息类型有"漂移开始、漂移结束、时间回拨",具体参考 Yitter.IdGenTest 的 Program.cs 启动代码。不过订阅ID异步通知会有细微的性能损失。 + +2.你可在外部系统的异步(async标记)方法中调用本算法,同步调用同样没问题。 + + diff --git a/C#.NET/source/.gitignore b/C#.NET/source/.gitignore new file mode 100644 index 0000000..1e8572c --- /dev/null +++ b/C#.NET/source/.gitignore @@ -0,0 +1,258 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates +*.editorconfig + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +**/.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ +dlldata.c + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +*.snupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml + + +# macOS +.DS_Store diff --git a/C#.NET/source/Yitter.IdGen.sln b/C#.NET/source/Yitter.IdGen.sln new file mode 100644 index 0000000..2cbc6ea --- /dev/null +++ b/C#.NET/source/Yitter.IdGen.sln @@ -0,0 +1,31 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.31005.135 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yitter.IdGenerator", "Yitter.IdGenerator\Yitter.IdGenerator.csproj", "{FF8DAF11-34E7-4842-ADF2-3722A1A5FBB2}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yitter.IdGenTest", "Yitter.IdGenTest\Yitter.IdGenTest.csproj", "{67426F7D-0A3B-4645-B4D7-5487215D3E2B}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {FF8DAF11-34E7-4842-ADF2-3722A1A5FBB2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FF8DAF11-34E7-4842-ADF2-3722A1A5FBB2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FF8DAF11-34E7-4842-ADF2-3722A1A5FBB2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FF8DAF11-34E7-4842-ADF2-3722A1A5FBB2}.Release|Any CPU.Build.0 = Release|Any CPU + {67426F7D-0A3B-4645-B4D7-5487215D3E2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {67426F7D-0A3B-4645-B4D7-5487215D3E2B}.Debug|Any CPU.Build.0 = Debug|Any CPU + {67426F7D-0A3B-4645-B4D7-5487215D3E2B}.Release|Any CPU.ActiveCfg = Release|Any CPU + {67426F7D-0A3B-4645-B4D7-5487215D3E2B}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {5C87B69B-CE8D-411F-AFAF-298C7BC7C2EA} + EndGlobalSection +EndGlobal diff --git a/C#.NET/source/Yitter.IdGenTest/GenTest.cs b/C#.NET/source/Yitter.IdGenTest/GenTest.cs new file mode 100644 index 0000000..b5383c4 --- /dev/null +++ b/C#.NET/source/Yitter.IdGenTest/GenTest.cs @@ -0,0 +1,49 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using Yitter.IdGenerator; + +namespace Yitter.OrgSystem.TestA +{ + public class GenTest + { + private IIdGenerator IdGen; + private Hashtable ids = new Hashtable(); + public IList idList = new List(); + private int GenIdCount; + private int WorkerId; + + + public GenTest(IIdGenerator idGen, int genIdCount, int workerId) + { + GenIdCount = genIdCount; + IdGen = idGen; + WorkerId = workerId; + } + + //public void GenId() + //{ + // Thread t = new Thread(new ThreadStart(Gen1Start)); + // t.Start(); + //} + + public void GenStart() + { + DateTime start = DateTime.Now; + + for (int i = 0; i < GenIdCount; i++) + { + var id = IdGen.NewLong(); + //ids.Add(id, i); + //idList.Add(id); + } + + DateTime end = DateTime.Now; + Console.WriteLine($"++++++++++++++++++++++++++++++++++++++++WorkerId: {WorkerId}, total: {(end - start).TotalMilliseconds} ms"); + Interlocked.Increment(ref Program.Count); + } + } +} diff --git a/C#.NET/source/Yitter.IdGenTest/Program.cs b/C#.NET/source/Yitter.IdGenTest/Program.cs new file mode 100644 index 0000000..fbdaf8f --- /dev/null +++ b/C#.NET/source/Yitter.IdGenTest/Program.cs @@ -0,0 +1,226 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Threading; +using Yitter.IdGenerator; + +namespace Yitter.OrgSystem.TestA +{ + class Program + { + + // 测试参数(默认配置下,最佳性能是10W/s) + static int genIdCount = 50000; // 计算ID数量(如果要验证50W效率,请将TopOverCostCount设置为20000或适当增加SeqBitLength) + static short method = 1; // 1-漂移算法,2-传统算法 + + + static bool single = true; + static bool outputLog = false; + static IIdGenerator IdGen = null; + static IList testList = new List(); + static bool checkResult = false; + public static int Count = 0; + static int workerCount = 1; + + + static void Main(string[] args) + { + Console.WriteLine("Hello World! C#"); + + var options = new IdGeneratorOptions() + { + Method = method, + WorkerId = 1, + + WorkerIdBitLength = 6, + SeqBitLength = 6, + TopOverCostCount = 2000, + + //MinSeqNumber = 1, + // MaxSeqNumber = 200, + + // BaseTime = DateTime.Now.AddYears(-10), + }; + + IdGen = new DefaultIdGenerator(options); + GenTest genTest = new GenTest(IdGen, genIdCount, options.WorkerId); + + // 首先测试一下 IdHelper 方法,获取单个Id + YitIdHelper.SetIdGenerator(options); + long newId = YitIdHelper.NextId(); + Console.WriteLine("====================================="); + Console.WriteLine("这是用方法 " + method + " 生成的 Id:" + newId); + + while (true) + { + //RunSingle(); + // Go(options); + CallDll(); + Thread.Sleep(1000); // 每隔1秒执行一次Go + } + } + + [DllImport("yitidgenc.dll", CallingConvention = CallingConvention.StdCall)] + public static extern long NextId(); + + [DllImport("yitidgenc.dll", CallingConvention = CallingConvention.StdCall)] + public static extern void SetWorkerId(uint workerId); + + [DllImport("yitidgenc.dll", CallingConvention = CallingConvention.StdCall)] + public static extern int TestId(); + + private static void CallDll() + { + try + { + + int i = 0; + long id = 0; + DateTime start = DateTime.Now; + + var ids = TestId(); + + //SetWorkerId(1); + + while (i < 50000) + { + id = NextId(); + i++; + } + DateTime end = DateTime.Now; + Console.WriteLine("id:" + id); + Console.WriteLine($"+++++++++++C# call rust dll, gen 5W, total: {(end - start).TotalMilliseconds} ms"); + } + catch (Exception ex) + { + Console.WriteLine(ex.Message); + } + } + + private static void RunSingle() + { + DateTime start = DateTime.Now; + + for (int i = 0; i < genIdCount; i++) + { + var id = IdGen.NewLong(); + } + + DateTime end = DateTime.Now; + Console.WriteLine($"++++++++++++++++++++++++++++++++++++++++, total: {(end - start).TotalMilliseconds} ms"); + Interlocked.Increment(ref Program.Count); + } + + private static void Go(IdGeneratorOptions options) + { + Count = 0; + testList = new List(); + + // ++++++++++++++++++++++++++++++++ + if (single) + { + if (IdGen == null) + { + IdGen = new DefaultIdGenerator(options); + } + + if (outputLog) + { + IdGen.GenIdActionAsync = (arg => + { + if (arg.ActionType == 1) + { + Console.WriteLine($">>>> {arg.WorkerId}:开始:{DateTime.Now.ToString("mm:ss:fff")}, 周期次序:{arg.TermIndex}"); + } + else if (arg.ActionType == 2) + { + Console.WriteLine($"<<<< {arg.WorkerId}:结束:{DateTime.Now.ToString("mm:ss:fff")},漂移 {arg.OverCostCountInOneTerm} 次,产生 {arg.GenCountInOneTerm} 个, 周期次序:{arg.TermIndex}"); + } + if (arg.ActionType == 8) + { + Console.WriteLine($"---- {arg.WorkerId}:AA结束:{DateTime.Now.ToString("mm:ss:fff")},时间回拨"); + } + }); + } + + for (int i = 1; i < workerCount + 1; i++) + { + Console.WriteLine("Gen:" + i); + var test = new GenTest(IdGen, genIdCount, i); + testList.Add(test); + // test.GenId(); + test.GenStart(); + } + } + else + { + for (int i = 1; i < workerCount + 1; i++) + { + IdGeneratorOptions newOptions = new IdGeneratorOptions() + { + WorkerId = (ushort)i, // workerId 不能设置为0 + WorkerIdBitLength = options.WorkerIdBitLength, + SeqBitLength = options.SeqBitLength, + MinSeqNumber = options.MinSeqNumber, + MaxSeqNumber = options.MaxSeqNumber, + Method = options.Method, + }; + + Console.WriteLine("Gen:" + i); + var idGen2 = new DefaultIdGenerator(newOptions); + var test = new GenTest(idGen2, genIdCount, i); + + if (outputLog) + { + idGen2.GenIdActionAsync = (arg => + { + Console.WriteLine($"{DateTime.Now.ToString("mm:ss:fff")} {arg.WorkerId} 漂移了 {arg.OverCostCountInOneTerm}, 顺序:{arg.TermIndex}"); + }); + } + + testList.Add(test); + // test.GenId(); + test.GenStart(); + } + } + + while (Count < workerCount) + { + //Console.WriteLine("Count:" + Count); + Thread.Sleep(1000); + } + //Console.WriteLine("Count:" + Count); + + if (!checkResult) + { + return; + } + + var dupCount = 0; + foreach (var id in testList[0].idList) + { + if (id == 0) + { + Console.WriteLine("############### 错误的ID:" + id + "###########"); + } + + for (int j = 1; j < testList.Count; j++) + { + if (testList[j].idList.Contains(id)) + { + dupCount++; + Console.WriteLine("xxxxxxxxxx 重复的ID:" + id); + } + } + } + + if (dupCount > 0) + { + Console.WriteLine($"重复数量:{dupCount}"); + } + + } + + } +} diff --git a/C#.NET/source/Yitter.IdGenTest/Properties/launchSettings.json b/C#.NET/source/Yitter.IdGenTest/Properties/launchSettings.json new file mode 100644 index 0000000..d27f545 --- /dev/null +++ b/C#.NET/source/Yitter.IdGenTest/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "Yitter.IdGenTest": { + "commandName": "Project", + "nativeDebugging": true + } + } +} \ No newline at end of file diff --git a/C#.NET/source/Yitter.IdGenTest/Yitter.IdGenTest.csproj b/C#.NET/source/Yitter.IdGenTest/Yitter.IdGenTest.csproj new file mode 100644 index 0000000..9ce00e5 --- /dev/null +++ b/C#.NET/source/Yitter.IdGenTest/Yitter.IdGenTest.csproj @@ -0,0 +1,23 @@ + + + + Exe + net5.0 + + + + latest + 1.0.2 + https://gitee.com/yitter/idgenerator + MIT + + + + x64 + + + + + + + diff --git a/C#.NET/source/Yitter.IdGenerator/Contract/IIdGenerator.cs b/C#.NET/source/Yitter.IdGenerator/Contract/IIdGenerator.cs new file mode 100644 index 0000000..22bd86e --- /dev/null +++ b/C#.NET/source/Yitter.IdGenerator/Contract/IIdGenerator.cs @@ -0,0 +1,29 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + * 版权协议:MIT + * 版权说明:只要保留本版权,你可以免费使用、修改、分发本代码。 + * 免责条款:任何因为本代码产生的系统、法律、政治、宗教问题,均与版权所有者无关。 + * + */ + +using System; + +namespace Yitter.IdGenerator +{ + public interface IIdGenerator + { + /// + /// 生成过程中产生的事件 + /// + Action GenIdActionAsync { get; set; } + + /// + /// 生成新的long型Id + /// + /// + long NewLong(); + + // Guid NewGuid(); + } +} diff --git a/C#.NET/source/Yitter.IdGenerator/Contract/ISnowWorker.cs b/C#.NET/source/Yitter.IdGenerator/Contract/ISnowWorker.cs new file mode 100644 index 0000000..1be6ac5 --- /dev/null +++ b/C#.NET/source/Yitter.IdGenerator/Contract/ISnowWorker.cs @@ -0,0 +1,22 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + * 版权协议:MIT + * 版权说明:只要保留本版权,你可以免费使用、修改、分发本代码。 + * 免责条款:任何因为本代码产生的系统、法律、政治、宗教问题,均与版权所有者无关。 + * + */ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Yitter.IdGenerator +{ + internal interface ISnowWorker + { + Action GenAction { get; set; } + + long NextId(); + } +} diff --git a/C#.NET/source/Yitter.IdGenerator/Contract/IdGeneratorOptions.cs b/C#.NET/source/Yitter.IdGenerator/Contract/IdGeneratorOptions.cs new file mode 100644 index 0000000..cf58fdf --- /dev/null +++ b/C#.NET/source/Yitter.IdGenerator/Contract/IdGeneratorOptions.cs @@ -0,0 +1,80 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + * 版权协议:MIT + * 版权说明:只要保留本版权,你可以免费使用、修改、分发本代码。 + * 免责条款:任何因为本代码产生的系统、法律、政治、宗教问题,均与版权所有者无关。 + * + */ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Yitter.IdGenerator +{ + public class IdGeneratorOptions + { + /// + /// 雪花计算方法 + /// (1-漂移算法|2-传统算法),默认1 + /// + public virtual short Method { get; set; } = 1; + + /// + /// 基础时间(UTC格式) + /// 不能超过当前系统时间 + /// + public virtual DateTime BaseTime { get; set; } = new DateTime(2020, 2, 20, 2, 20, 2, 20, DateTimeKind.Utc); + + /// + /// 机器码 + /// 与 WorkerIdBitLength 有关系 + /// (ushort类型,最大值65535,如果有更高要求,请修改数据类型,或联系作者) + /// + public virtual ushort WorkerId { get; set; } = 0; + + /// + /// 机器码位长 + /// 范围:1-21(要求:序列数位长+机器码位长不超过22)。 + /// 建议范围:6-12。 + /// + public virtual byte WorkerIdBitLength { get; set; } = 6;//10; + + /// + /// 序列数位长 + /// 范围:2-21(要求:序列数位长+机器码位长不超过22)。 + /// 建议范围:6-14。 + /// + public virtual byte SeqBitLength { get; set; } = 6;//10; + + /// + /// 最大序列数(含) + /// (由SeqBitLength计算的最大值) + /// + public virtual int MaxSeqNumber { get; set; } = 0; + + /// + /// 最小序列数(含) + /// 默认5,不小于1,不大于MaxSeqNumber + /// + public virtual ushort MinSeqNumber { get; set; } = 5; + + /// + /// 最大漂移次数(含), + /// 默认2000,推荐范围500-10000(与计算能力有关) + /// + public virtual int TopOverCostCount { get; set; } = 2000; + + + public IdGeneratorOptions() + { + + } + + public IdGeneratorOptions(ushort workerId) + { + WorkerId = workerId; + } + } +} diff --git a/C#.NET/source/Yitter.IdGenerator/Contract/OverCostActionArg.cs b/C#.NET/source/Yitter.IdGenerator/Contract/OverCostActionArg.cs new file mode 100644 index 0000000..8a71a1d --- /dev/null +++ b/C#.NET/source/Yitter.IdGenerator/Contract/OverCostActionArg.cs @@ -0,0 +1,57 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + * 版权协议:MIT + * 版权说明:只要保留本版权,你可以免费使用、修改、分发本代码。 + * 免责条款:任何因为本代码产生的系统、法律、政治、宗教问题,均与版权所有者无关。 + * + */ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Yitter.IdGenerator +{ + /// + /// Id生成时回调参数 + /// + public class OverCostActionArg + { + /// + /// 事件类型 + /// 1-开始,2-结束,8-漂移 + /// + public virtual int ActionType { get; set; } + /// + /// 时间戳 + /// + public virtual long TimeTick { get; set; } + /// + /// 机器码 + /// + public virtual ushort WorkerId { get; set; } + /// + /// 漂移计算次数 + /// + public virtual int OverCostCountInOneTerm { get; set; } + /// + /// 漂移期间生产ID个数 + /// + public virtual int GenCountInOneTerm { get; set; } + /// + /// 漂移周期 + /// + public virtual int TermIndex { get; set; } + + public OverCostActionArg(ushort workerId, long timeTick, int actionType = 0, int overCostCountInOneTerm = 0, int genCountWhenOverCost = 0, int index = 0) + { + ActionType = actionType; + TimeTick = timeTick; + WorkerId = workerId; + OverCostCountInOneTerm = overCostCountInOneTerm; + GenCountInOneTerm = genCountWhenOverCost; + TermIndex = index; + } + } +} diff --git a/C#.NET/source/Yitter.IdGenerator/Core/SnowWorkerM1.cs b/C#.NET/source/Yitter.IdGenerator/Core/SnowWorkerM1.cs new file mode 100644 index 0000000..9a11b8c --- /dev/null +++ b/C#.NET/source/Yitter.IdGenerator/Core/SnowWorkerM1.cs @@ -0,0 +1,350 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + * 版权协议:MIT + * 版权说明:只要保留本版权,你可以免费使用、修改、分发本代码。 + * 免责条款:任何因为本代码产生的系统、法律、政治、宗教问题,均与版权所有者无关。 + * + */ + +using System; +using System.Threading; +using System.Threading.Tasks; + +namespace Yitter.IdGenerator +{ + /// + /// 雪花漂移算法 + /// + internal class SnowWorkerM1 : ISnowWorker + { + /// + /// 基础时间 + /// + protected readonly DateTime BaseTime; + + /// + /// 机器码 + /// + protected readonly ushort WorkerId = 0; + + /// + /// 机器码位长 + /// + protected readonly byte WorkerIdBitLength = 0; + + /// + /// 自增序列数位长 + /// + protected readonly byte SeqBitLength = 0; + + /// + /// 最大序列数(含) + /// + protected readonly int MaxSeqNumber = 0; + + /// + /// 最小序列数(含) + /// + protected readonly ushort MinSeqNumber = 0; + + /// + /// 最大漂移次数 + /// + protected readonly int TopOverCostCount = 0; + + protected readonly byte _TimestampShift = 0; + protected static object _SyncLock = new object(); + + protected ushort _CurrentSeqNumber; + protected long _LastTimeTick = -1L; + protected long _TurnBackTimeTick = -1L; + protected byte _TurnBackIndex = 0; + + protected bool _IsOverCost = false; + protected int _OverCostCountInOneTerm = 0; + protected int _GenCountInOneTerm = 0; + protected int _TermIndex = 0; + + //private static long _StartTimeTick = 0; + //private static long _BaseTimeTick = 0; + + public Action GenAction { get; set; } + + + public SnowWorkerM1(IdGeneratorOptions options) + { + WorkerId = options.WorkerId; + WorkerIdBitLength = options.WorkerIdBitLength; + SeqBitLength = options.SeqBitLength; + MaxSeqNumber = options.MaxSeqNumber; + MinSeqNumber = options.MinSeqNumber; + TopOverCostCount = options.TopOverCostCount; + + if (options.BaseTime != DateTime.MinValue) + { + BaseTime = options.BaseTime; + } + + if (WorkerId < 1) + { + WorkerId = (ushort)DateTime.Now.Millisecond; + } + + if (SeqBitLength == 0) + { + SeqBitLength = 6; + } + + if (WorkerIdBitLength == 0) + { + WorkerIdBitLength = 6; + } + + if (MaxSeqNumber == 0) + { + MaxSeqNumber = (1 << SeqBitLength) - 1; + } + + _TimestampShift = (byte)(WorkerIdBitLength + SeqBitLength); + _CurrentSeqNumber = options.MinSeqNumber; + + //_BaseTimeTick = BaseTime.Ticks; + //_StartTimeTick = (long)(DateTime.UtcNow.Subtract(BaseTime).TotalMilliseconds) - Environment.TickCount; + } + + + private void DoGenIdAction(OverCostActionArg arg) + { + Task.Run(() => + { + GenAction(arg); + }); + } + + private void BeginOverCostAction(in long useTimeTick) + { + return; + + if (GenAction == null) + { + return; + } + + DoGenIdAction(new OverCostActionArg( + WorkerId, + useTimeTick, + 1, + _OverCostCountInOneTerm, + _GenCountInOneTerm, + _TermIndex)); + } + + private void EndOverCostAction(in long useTimeTick) + { + if (_TermIndex > 10000) + { + _TermIndex = 0; + } + return; + + if (GenAction == null) + { + return; + } + + DoGenIdAction(new OverCostActionArg( + WorkerId, + useTimeTick, + 2, + _OverCostCountInOneTerm, + _GenCountInOneTerm, + _TermIndex)); + } + + private void BeginTurnBackAction(in long useTimeTick) + { + return; + + if (GenAction == null) + { + return; + } + + DoGenIdAction(new OverCostActionArg( + WorkerId, + useTimeTick, + 8, + 0, + 0, + _TurnBackIndex)); + } + + private void EndTurnBackAction(in long useTimeTick) + { + return; + + if (GenAction == null) + { + return; + } + + DoGenIdAction(new OverCostActionArg( + WorkerId, + useTimeTick, + 9, + 0, + 0, + _TurnBackIndex)); + } + + private long NextOverCostId() + { + long currentTimeTick = GetCurrentTimeTick(); + + if (currentTimeTick > _LastTimeTick) + { + EndOverCostAction(currentTimeTick); + + _LastTimeTick = currentTimeTick; + _CurrentSeqNumber = MinSeqNumber; + _IsOverCost = false; + _OverCostCountInOneTerm = 0; + _GenCountInOneTerm = 0; + + return CalcId(_LastTimeTick); + } + + if (_OverCostCountInOneTerm >= TopOverCostCount) + { + EndOverCostAction(currentTimeTick); + + _LastTimeTick = GetNextTimeTick(); + _CurrentSeqNumber = MinSeqNumber; + _IsOverCost = false; + _OverCostCountInOneTerm = 0; + _GenCountInOneTerm = 0; + + return CalcId(_LastTimeTick); + } + + if (_CurrentSeqNumber > MaxSeqNumber) + { + _LastTimeTick++; + _CurrentSeqNumber = MinSeqNumber; + _IsOverCost = true; + _OverCostCountInOneTerm++; + _GenCountInOneTerm++; + + return CalcId(_LastTimeTick); + } + + _GenCountInOneTerm++; + return CalcId(_LastTimeTick); + } + + private long NextNormalId() + { + long currentTimeTick = GetCurrentTimeTick(); + + if (currentTimeTick < _LastTimeTick) + { + if (_TurnBackTimeTick < 1) + { + _TurnBackTimeTick = _LastTimeTick - 1; + _TurnBackIndex++; + + // 每毫秒序列数的前5位是预留位,0用于手工新值,1-4是时间回拨次序 + // 最多4次回拨(防止回拨重叠) + if (_TurnBackIndex > 4) + { + _TurnBackIndex = 1; + } + + BeginTurnBackAction(_TurnBackTimeTick); + } + + Thread.Sleep(10); + return CalcTurnBackId(_TurnBackTimeTick); + } + + // 时间追平时,_TurnBackTimeTick清零 + if (_TurnBackTimeTick > 0) + { + EndTurnBackAction(_TurnBackTimeTick); + _TurnBackTimeTick = 0; + } + + if (currentTimeTick > _LastTimeTick) + { + _LastTimeTick = currentTimeTick; + _CurrentSeqNumber = MinSeqNumber; + + return CalcId(_LastTimeTick); + } + + if (_CurrentSeqNumber > MaxSeqNumber) + { + BeginOverCostAction(currentTimeTick); + + _TermIndex++; + _LastTimeTick++; + _CurrentSeqNumber = MinSeqNumber; + _IsOverCost = true; + _OverCostCountInOneTerm = 1; + _GenCountInOneTerm = 1; + + return CalcId(_LastTimeTick); + } + + return CalcId(_LastTimeTick); + } + + private long CalcId(in long useTimeTick) + { + var result = ((useTimeTick << _TimestampShift) + + ((long)WorkerId << SeqBitLength) + + (uint)_CurrentSeqNumber); + + _CurrentSeqNumber++; + return result; + } + + private long CalcTurnBackId(in long useTimeTick) + { + var result = ((useTimeTick << _TimestampShift) + + ((long)WorkerId << SeqBitLength) + _TurnBackIndex); + + _TurnBackTimeTick--; + return result; + } + + protected virtual long GetCurrentTimeTick() + { + //return (long)(DateTime.UtcNow - BaseTime).Ticks; + //return (long)(_StartTimeTick + Environment.TickCount); + return (long)(DateTime.UtcNow - BaseTime).TotalMilliseconds; + } + + protected virtual long GetNextTimeTick() + { + long tempTimeTicker = GetCurrentTimeTick(); + + while (tempTimeTicker <= _LastTimeTick) + { + tempTimeTicker = GetCurrentTimeTick(); + } + + return tempTimeTicker; + } + + + public virtual long NextId() + { + lock (_SyncLock) + { + return _IsOverCost ? NextOverCostId() : NextNormalId(); + } + } + } +} diff --git a/C#.NET/source/Yitter.IdGenerator/Core/SnowWorkerM2.cs b/C#.NET/source/Yitter.IdGenerator/Core/SnowWorkerM2.cs new file mode 100644 index 0000000..4515ab9 --- /dev/null +++ b/C#.NET/source/Yitter.IdGenerator/Core/SnowWorkerM2.cs @@ -0,0 +1,58 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + * 版权协议:MIT + * 版权说明:只要保留本版权,你可以免费使用、修改、分发本代码。 + * 免责条款:任何因为本代码产生的系统、法律、政治、宗教问题,均与版权所有者无关。 + * + */ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Yitter.IdGenerator +{ + /// + /// 常规雪花算法 + /// + internal class SnowWorkerM2 : SnowWorkerM1 + { + public SnowWorkerM2(IdGeneratorOptions options) : base(options) + { + + } + + public override long NextId() + { + lock (_SyncLock) + { + long currentTimeTick = GetCurrentTimeTick(); + + if (_LastTimeTick == currentTimeTick) + { + if (_CurrentSeqNumber++ > MaxSeqNumber) + { + _CurrentSeqNumber = MinSeqNumber; + currentTimeTick = GetNextTimeTick(); + } + } + else + { + _CurrentSeqNumber = MinSeqNumber; + } + + if (currentTimeTick < _LastTimeTick) + { + throw new Exception(string.Format("Time error for {0} milliseconds", _LastTimeTick - currentTimeTick)); + } + + _LastTimeTick = currentTimeTick; + var result = ((currentTimeTick << _TimestampShift) + ((long)WorkerId << SeqBitLength) + (uint)_CurrentSeqNumber); + + return result; + } + } + + } +} diff --git a/C#.NET/source/Yitter.IdGenerator/DefaultIdGenerator.cs b/C#.NET/source/Yitter.IdGenerator/DefaultIdGenerator.cs new file mode 100644 index 0000000..a59cdb0 --- /dev/null +++ b/C#.NET/source/Yitter.IdGenerator/DefaultIdGenerator.cs @@ -0,0 +1,100 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + * 版权协议:MIT + * 版权说明:只要保留本版权,你可以免费使用、修改、分发本代码。 + * 免责条款:任何因为本代码产生的系统、法律、政治、宗教问题,均与版权所有者无关。 + * + */ + +using System; +using System.Collections.Generic; +using System.Text; +using System.Threading; + +namespace Yitter.IdGenerator +{ + /// + /// 默认实现 + /// + public class DefaultIdGenerator : IIdGenerator + { + private ISnowWorker _SnowWorker { get; set; } + + public Action GenIdActionAsync + { + get => _SnowWorker.GenAction; + set => _SnowWorker.GenAction = value; + } + + + public DefaultIdGenerator(IdGeneratorOptions options) + { + if (options == null) + { + throw new ApplicationException("options error."); + } + + if (options.BaseTime < DateTime.Now.AddYears(-50) || options.BaseTime > DateTime.Now) + { + throw new ApplicationException("BaseTime error."); + } + + if (options.WorkerIdBitLength <= 0) + { + throw new ApplicationException("WorkerIdBitLength error.(range:[1, 21])"); + } + if (options.SeqBitLength + options.WorkerIdBitLength > 22) + { + throw new ApplicationException("error:WorkerIdBitLength + SeqBitLength <= 22"); + } + + var maxWorkerIdNumber = (1 << options.WorkerIdBitLength) - 1; + if (options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber) + { + throw new ApplicationException("WorkerId error. (range:[0, " + (maxWorkerIdNumber > 0 ? maxWorkerIdNumber : 63) + "]"); + } + + if (options.SeqBitLength < 2 || options.SeqBitLength > 21) + { + throw new ApplicationException("SeqBitLength error. (range:[2, 21])"); + } + + var maxSeqNumber = (1 << options.SeqBitLength) - 1; + if (options.MaxSeqNumber < 0 || options.MaxSeqNumber > maxSeqNumber) + { + throw new ApplicationException("MaxSeqNumber error. (range:[1, " + maxSeqNumber + "]"); + } + + var maxValue = maxSeqNumber; + if (options.MinSeqNumber < 1 || options.MinSeqNumber > maxValue) + { + throw new ApplicationException("MinSeqNumber error. (range:[1, " + maxValue + "]"); + } + + switch (options.Method) + { + case 1: + _SnowWorker = new SnowWorkerM1(options); + break; + case 2: + _SnowWorker = new SnowWorkerM2(options); + break; + default: + _SnowWorker = new SnowWorkerM1(options); + break; + } + + if (options.Method == 1) + { + Thread.Sleep(500); + } + } + + + public long NewLong() + { + return _SnowWorker.NextId(); + } + } +} diff --git a/C#.NET/source/Yitter.IdGenerator/YitIdHelper.cs b/C#.NET/source/Yitter.IdGenerator/YitIdHelper.cs new file mode 100644 index 0000000..c7bee20 --- /dev/null +++ b/C#.NET/source/Yitter.IdGenerator/YitIdHelper.cs @@ -0,0 +1,53 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + * 版权协议:MIT + * 版权说明:只要保留本版权,你可以免费使用、修改、分发本代码。 + * 免责条款:任何因为本代码产生的系统、法律、政治、宗教问题,均与版权所有者无关。 + * + */ + +using System; +using System.Collections.Generic; +using System.Text; + +namespace Yitter.IdGenerator +{ + /// + /// 这是一个调用的例子,默认情况下,单机集成者可以直接使用 NextId()。 + /// + public class YitIdHelper + { + private static IIdGenerator _IdGenInstance = null; + + public static IIdGenerator IdGenInstance => _IdGenInstance; + + /// + /// 设置参数,建议程序初始化时执行一次 + /// + /// + public static void SetIdGenerator(IdGeneratorOptions options) + { + _IdGenInstance = new DefaultIdGenerator(options); + } + + /// + /// 生成新的Id + /// 调用本方法前,请确保调用了 SetIdGenerator 方法做初始化。 + /// 否则将会初始化一个WorkerId为1的对象。 + /// + /// + public static long NextId() + { + if (_IdGenInstance == null) + { + _IdGenInstance = new DefaultIdGenerator( + new IdGeneratorOptions() { WorkerId = 1 } + ); + } + + return _IdGenInstance.NewLong(); + } + + } +} diff --git a/C#.NET/source/Yitter.IdGenerator/Yitter.IdGenerator.csproj b/C#.NET/source/Yitter.IdGenerator/Yitter.IdGenerator.csproj new file mode 100644 index 0000000..2486ca0 --- /dev/null +++ b/C#.NET/source/Yitter.IdGenerator/Yitter.IdGenerator.csproj @@ -0,0 +1,29 @@ + + + + netstandard2.0 + + + + latest + true + Shorter ID and faster generation with a new snowflake drift algorithm. The core is to shorten the ID length, but also can have a very high instantaneous concurrent processing capacity (50W/0.1s), and powerful configuration capacity. + +一种全新的雪花漂移算法,让ID更短、生成速度更快。 核心在于缩短ID长度的同时,还能拥有极高瞬时并发处理量(50W/0.1s),及强大的配置能力。 + Yitter.IdGenerator + Yitter.IdGenerator + IdGenerator + Yitter + Yitter + Yitter + https://gitee.com/yitter/idgenerator + MIT + 1.0.9 + + + + + 5 + + + diff --git a/C/README.md b/C/README.md new file mode 100644 index 0000000..4b7ea56 --- /dev/null +++ b/C/README.md @@ -0,0 +1,8 @@ +# idgenerator + +## ˵ + +1.Ĭ Linux CMake + +2. Windows Ҫ Cygwin MinGW + diff --git a/C/source/.gitignore b/C/source/.gitignore new file mode 100644 index 0000000..a574516 --- /dev/null +++ b/C/source/.gitignore @@ -0,0 +1,258 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates +*.editorconfig + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +**/.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +*.snupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml +target/ +cmake-build*/ + +# macOS +.DS_Store diff --git a/C/source/CMakeLists.txt b/C/source/CMakeLists.txt new file mode 100644 index 0000000..d80bdf8 --- /dev/null +++ b/C/source/CMakeLists.txt @@ -0,0 +1,27 @@ +cmake_minimum_required(VERSION 3.17) +project(YitIdGen) +set(CMAKE_C_STANDARD 11) + +#set(CMAKE_BUILD_TYPE DEBUG) +#set(CMAKE_BUILD_TYPE RELEASE) + +aux_source_directory(. DIR_SRCS) +add_subdirectory(idgen) + +#编译动态库 +set(LIB_SRC YitIdHelper.h YitIdHelper.c) +add_library(YitIdGenLib SHARED ${LIB_SRC}) +target_link_libraries(YitIdGenLib idgen) +set_target_properties(YitIdGenLib PROPERTIES + LINKER_LANGUAGE C + OUTPUT_NAME "yitidgenc" + PREFIX "") + +##编译执行文件 +#set(LIB_SRC YitIdHelper.h YitIdHelper.c) +#add_library(YitIdHelper ${LIB_SRC}) +#add_executable(YitIdGen main.c) +#target_link_libraries(YitIdGen YitIdHelper) +#target_link_libraries(YitIdGen idgen) + + diff --git a/C/source/YitIdHelper.c b/C/source/YitIdHelper.c new file mode 100644 index 0000000..c3b695d --- /dev/null +++ b/C/source/YitIdHelper.c @@ -0,0 +1,30 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +#include +#include +#include "YitIdHelper.h" +#include "idgen/IdGenerator.h" + +extern void SetIdGenerator(IdGeneratorOptions options) { + SetOptions(options); +} + +extern void SetWorkerId(uint32_t workerId) { + IdGeneratorOptions options = BuildIdGenOptions(workerId); + // SetOptions(options); + SetIdGenerator(options); +} + +extern uint64_t NextId() { + return GetIdGenInstance()->NextId(); +// IdGenerator *generator = GetIdGenInstance(); +// uint64_t id = generator->NextId(); +// free(generator); +// return id; +} + +extern uint64_t TestId() { + return 123456; +} diff --git a/C/source/YitIdHelper.h b/C/source/YitIdHelper.h new file mode 100644 index 0000000..2181b22 --- /dev/null +++ b/C/source/YitIdHelper.h @@ -0,0 +1,21 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +#pragma once + +#include "idgen/IdGenOptions.h" +#include "idgen/common.h" + + +TAP_DLLEXPORT +extern void TAP_STDCALL SetIdGenerator(IdGeneratorOptions options); + +TAP_DLLEXPORT +extern void TAP_STDCALL SetWorkerId(uint32_t workerId); + +TAP_DLLEXPORT +extern uint64_t TAP_STDCALL NextId(); + +TAP_DLLEXPORT +extern uint64_t TAP_STDCALL TestId(); diff --git a/C/source/idgen/CMakeLists.txt b/C/source/idgen/CMakeLists.txt new file mode 100644 index 0000000..9b9e8e1 --- /dev/null +++ b/C/source/idgen/CMakeLists.txt @@ -0,0 +1,7 @@ +aux_source_directory(. DIR_LIB_SRCS) +add_library(idgen ${DIR_LIB_SRCS}) + +#SET(LIB_SRC ../YitIdHelper.h ../YitIdHelper.c) +#add_library(YitIdGenLib SHARED ${LIB_SRC}) +#target_link_libraries(YitIdGenLib IdGen) + diff --git a/C/source/idgen/IdGenOptions.c b/C/source/idgen/IdGenOptions.c new file mode 100644 index 0000000..440d671 --- /dev/null +++ b/C/source/idgen/IdGenOptions.c @@ -0,0 +1,34 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +#include "IdGenOptions.h" + + +extern IdGeneratorOptions BuildIdGenOptions(uint32_t workerId) { + IdGeneratorOptions options; + + options.Method = 1; + options.BaseTime = 1582136402000; + options.WorkerId = workerId; + options.WorkerIdBitLength = 6; + options.SeqBitLength = 6; + options.MaxSeqNumber = 0; + options.MinSeqNumber = 5; + options.TopOverCostCount = 2000; + + return options; + +// IdGeneratorOptions *options = (IdGeneratorOptions *) malloc(sizeof(IdGeneratorOptions)); +// +// options->Method = 1; +// options->BaseTime = 1582136402000; +// options->WorkerId = workerId; +// options->WorkerIdBitLength = 6; +// options->SeqBitLength = 6; +// options->MaxSeqNumber = 63; +// options->MinSeqNumber = 5; +// options->TopOverCostCount = 2000; +// +// return options; +} diff --git a/C/source/idgen/IdGenOptions.h b/C/source/idgen/IdGenOptions.h new file mode 100644 index 0000000..a50aeaf --- /dev/null +++ b/C/source/idgen/IdGenOptions.h @@ -0,0 +1,31 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +#pragma once + +#include + + +typedef struct IdGenOptions { + /// 雪花计算方法,(1-漂移算法|2-传统算法),默认1 + uint8_t Method; + /// 基础时间(ms单位),不能超过当前系统时间 + uint64_t BaseTime; + /// 机器码,与 WorkerIdBitLength 有关系 + uint32_t WorkerId; + /// 机器码位长,范围:1-21(要求:序列数位长+机器码位长不超过22) + uint8_t WorkerIdBitLength; + /// 序列数位长,范围:2-21(要求:序列数位长+机器码位长不超过22) + uint8_t SeqBitLength; + /// 最大序列数(含),(由 SeqBitLength 计算的最大值) + uint32_t MaxSeqNumber; + /// 最小序列数(含),默认5,不小于5,不大于 MaxSeqNumber + uint32_t MinSeqNumber; + /// 最大漂移次数(含),默认2000,推荐范围 500-20000(与计算能力有关) + uint32_t TopOverCostCount; + +} IdGeneratorOptions; + +extern IdGeneratorOptions BuildIdGenOptions(uint32_t workerId); + diff --git a/C/source/idgen/IdGenerator.c b/C/source/idgen/IdGenerator.c new file mode 100644 index 0000000..74b76c6 --- /dev/null +++ b/C/source/idgen/IdGenerator.c @@ -0,0 +1,107 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +#include +#include +#include +#include +#include +#include "IdGenerator.h" + + +static inline uint64_t WorkerM1Id() { + return WorkerM1NextId(_idGenerator->Worker); +} + +static inline uint64_t WorkerM2Id() { + return WorkerM2NextId(_idGenerator->Worker); +} + + +extern IdGenerator *GetIdGenInstance() { + if (_idGenerator != NULL) + return _idGenerator; + else { + _idGenerator = (IdGenerator *) malloc(sizeof(IdGenerator)); + _idGenerator->Worker = NewSnowFlakeWorker(); + return _idGenerator; + } +} + +extern void SetOptions(IdGeneratorOptions options) { + if (GetIdGenInstance() == NULL) { + exit(1); + } + + // BaseTime + if (options.BaseTime == 0) { + _idGenerator->Worker->BaseTime = 1582136402000; + } else if (options.BaseTime < 631123200000 || options.BaseTime > GetCurrentTime()) { + perror("BaseTime error."); + exit(1); + } else { + _idGenerator->Worker->BaseTime = options.BaseTime; + } + + // WorkerIdBitLength + if (options.WorkerIdBitLength <= 0) { + perror("WorkerIdBitLength error.(range:[1, 21])"); + exit(1); + } + if (options.SeqBitLength + options.WorkerIdBitLength > 22) { + perror("error:WorkerIdBitLength + SeqBitLength <= 22"); + exit(1); + } else { +// _idGenerator->Worker->WorkerIdBitLength = options.WorkerIdBitLength; + _idGenerator->Worker->WorkerIdBitLength = options.WorkerIdBitLength <= 0 ? 6 : options.WorkerIdBitLength; + } + + // WorkerId + uint32_t maxWorkerIdNumber = (1 << options.WorkerIdBitLength) - 1; + if (options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber) { + perror("WorkerId error. (range:[0, {2^options.WorkerIdBitLength-1]}"); + exit(1); + } else { + _idGenerator->Worker->WorkerId = options.WorkerId; + } + + // SeqBitLength + if (options.SeqBitLength < 2 || options.SeqBitLength > 21) { + perror("SeqBitLength error. (range:[2, 21])"); + exit(1); + } else { +// _idGenerator->Worker->SeqBitLength = options.SeqBitLength; + _idGenerator->Worker->SeqBitLength = options.SeqBitLength <= 0 ? 6 : options.SeqBitLength; + } + + // MaxSeqNumber + uint32_t maxSeqNumber = (1 << options.SeqBitLength) - 1; + if (options.MaxSeqNumber > maxSeqNumber) { + perror("MaxSeqNumber error. (range:[1, {2^options.SeqBitLength-1}]"); + exit(1); + } else { + _idGenerator->Worker->MaxSeqNumber = options.MaxSeqNumber <= 0 ? maxSeqNumber : options.MaxSeqNumber; + } + + // MinSeqNumber + if (options.MinSeqNumber > maxSeqNumber || options.MinSeqNumber < 5) { + perror("MinSeqNumber error. (range:[5, {options.MinSeqNumber}]"); + exit(1); + } else { + _idGenerator->Worker->MinSeqNumber = options.MinSeqNumber <= 0 ? 5 : options.MinSeqNumber; + } + + _idGenerator->Worker->TopOverCostCount = options.TopOverCostCount <= 0 ? 2000 : options.TopOverCostCount; + _idGenerator->Worker->_TimestampShift = options.WorkerIdBitLength + options.SeqBitLength; + _idGenerator->Worker->_CurrentSeqNumber = options.MinSeqNumber; + + _idGenerator->Worker->Method = options.Method; + if (options.Method == 2) { + _idGenerator->NextId = WorkerM2Id; + } else { + _idGenerator->NextId = WorkerM1Id; + sleep(1); + } +} + diff --git a/C/source/idgen/IdGenerator.h b/C/source/idgen/IdGenerator.h new file mode 100644 index 0000000..f9841b7 --- /dev/null +++ b/C/source/idgen/IdGenerator.h @@ -0,0 +1,30 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +#pragma once + +#include +#include +#include +#include +#include +#include "IdGenOptions.h" +#include "SnowWorkerM1.h" +#include "SnowWorkerM2.h" + + +typedef struct IdGenerator { + SnowFlakeWorker *Worker; + + uint64_t (*NextId)(); + +} IdGenerator; + + +static IdGenerator *_idGenerator = NULL; + +extern IdGenerator *GetIdGenInstance(); + +extern void SetOptions(IdGeneratorOptions options); + diff --git a/C/source/idgen/SnowWorkerM1.c b/C/source/idgen/SnowWorkerM1.c new file mode 100644 index 0000000..e35102b --- /dev/null +++ b/C/source/idgen/SnowWorkerM1.c @@ -0,0 +1,161 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 代码翻译:amuluowin + * 代码修订:yitter + * 开源地址:https://gitee.com/yitter/idgenerator + */ +#include +#include +#include +#include +#include "SnowWorkerM1.h" + + +pthread_mutex_t ThreadMutex = PTHREAD_MUTEX_INITIALIZER; + +static void EndOverCostAction(uint64_t useTimeTick, SnowFlakeWorker *worker); + +static uint64_t NextOverCostId(SnowFlakeWorker *worker); + +static uint64_t NextNormalId(SnowFlakeWorker *worker); + +static uint64_t CalcId(SnowFlakeWorker *worker); + +static uint64_t CalcTurnBackId(SnowFlakeWorker *worker); + + +static inline void EndOverCostAction(uint64_t useTimeTick, SnowFlakeWorker *worker) { + if (worker->_TermIndex > 10000) { + worker->_TermIndex = 0; + } +} + +static inline uint64_t NextOverCostId(SnowFlakeWorker *worker) { + uint64_t currentTimeTick = GetCurrentTimeTick(worker); + if (currentTimeTick > worker->_LastTimeTick) { + EndOverCostAction(currentTimeTick, worker); + worker->_LastTimeTick = currentTimeTick; + worker->_CurrentSeqNumber = worker->MinSeqNumber; + worker->_IsOverCost = false; + worker->_OverCostCountInOneTerm = 0; + worker->_GenCountInOneTerm = 0; + return CalcId(worker); + } + if (worker->_OverCostCountInOneTerm > worker->TopOverCostCount) { + EndOverCostAction(currentTimeTick, worker); + worker->_LastTimeTick = GetNextTimeTick(worker); + worker->_CurrentSeqNumber = worker->MinSeqNumber; + worker->_IsOverCost = false; + worker->_OverCostCountInOneTerm = 0; + worker->_GenCountInOneTerm = 0; + return CalcId(worker); + } + if (worker->_CurrentSeqNumber > worker->MaxSeqNumber) { + worker->_LastTimeTick++; + worker->_CurrentSeqNumber = worker->MinSeqNumber; + worker->_IsOverCost = true; + worker->_OverCostCountInOneTerm++; + worker->_GenCountInOneTerm++; + return CalcId(worker); + } + + worker->_GenCountInOneTerm++; + return CalcId(worker); +} + +static inline uint64_t NextNormalId(SnowFlakeWorker *worker) { + uint64_t currentTimeTick = GetCurrentTimeTick(worker); + if (currentTimeTick < worker->_LastTimeTick) { + if (worker->_TurnBackTimeTick < 1) { + worker->_TurnBackTimeTick = worker->_LastTimeTick - 1; + worker->_TurnBackIndex++; + if (worker->_TurnBackIndex > 4) { + worker->_TurnBackIndex = 1; + } + } + return CalcTurnBackId(worker); + } + if (worker->_TurnBackTimeTick > 0) { + worker->_TurnBackTimeTick = 0; + } + if (currentTimeTick > worker->_LastTimeTick) { + worker->_LastTimeTick = currentTimeTick; + worker->_CurrentSeqNumber = worker->MinSeqNumber; + return CalcId(worker); + } + if (worker->_CurrentSeqNumber > worker->MaxSeqNumber) { + worker->_TermIndex++; + worker->_LastTimeTick++; + worker->_CurrentSeqNumber = worker->MinSeqNumber; + worker->_IsOverCost = true; + worker->_OverCostCountInOneTerm = 1; + worker->_GenCountInOneTerm = 1; + return CalcId(worker); + } + return CalcId(worker); +} + +static inline uint64_t CalcId(SnowFlakeWorker *worker) { + uint64_t result = (worker->_LastTimeTick << worker->_TimestampShift) | (worker->WorkerId << worker->SeqBitLength) | + (worker->_CurrentSeqNumber); + worker->_CurrentSeqNumber++; + return result; +} + +static inline uint64_t CalcTurnBackId(SnowFlakeWorker *worker) { + uint64_t result = (worker->_LastTimeTick << worker->_TimestampShift) | (worker->WorkerId << worker->SeqBitLength) | + (worker->_TurnBackTimeTick); + worker->_TurnBackTimeTick--; + return result; +} + + +extern SnowFlakeWorker *NewSnowFlakeWorker() { + SnowFlakeWorker *worker = (SnowFlakeWorker *) malloc(sizeof(SnowFlakeWorker)); + worker->_IsOverCost = false; + worker->_LastTimeTick = 0; + worker->_TurnBackTimeTick = 0; + worker->_TurnBackIndex = 0; + worker->_OverCostCountInOneTerm = 0; + worker->_GenCountInOneTerm = 0; + worker->_TermIndex = 0; + + return worker; +} + +extern uint64_t WorkerM1NextId(SnowFlakeWorker *worker) { + pthread_mutex_lock(&ThreadMutex); + uint64_t id = worker->_IsOverCost ? NextOverCostId(worker) : NextNormalId(worker); + pthread_mutex_unlock(&ThreadMutex); + return id; +} + +extern uint64_t GetCurrentTimeTick(SnowFlakeWorker *worker) { + struct timeval tv; + gettimeofday(&tv, NULL); + return ((uint64_t) tv.tv_sec * 1000 + tv.tv_usec / 1000 - worker->BaseTime); +} + +extern uint64_t GetCurrentTime() { + struct timeval tv; + gettimeofday(&tv, NULL); + return ((uint64_t) (tv.tv_sec)) * 1000 + tv.tv_usec / 1000; + + //static struct timeb t1; + // ftime(&t1); + // return (uint64_t) ((t1.time * 1000 + t1.millitm)); +} + +extern uint64_t GetCurrentMicroTime() { + struct timeval tv; + gettimeofday(&tv, NULL); + return ((uint64_t) tv.tv_sec * 1000000 + tv.tv_usec); +} + +extern uint64_t GetNextTimeTick(SnowFlakeWorker *worker) { + uint64_t tempTimeTicker = GetCurrentTimeTick(worker); + while (tempTimeTicker <= worker->_LastTimeTick) { + tempTimeTicker = GetCurrentTimeTick(worker); + } + return tempTimeTicker; +} diff --git a/C/source/idgen/SnowWorkerM1.h b/C/source/idgen/SnowWorkerM1.h new file mode 100644 index 0000000..d2d6925 --- /dev/null +++ b/C/source/idgen/SnowWorkerM1.h @@ -0,0 +1,53 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 代码翻译:amuluowin + * 代码修订:yitter + * 开源地址:https://gitee.com/yitter/idgenerator + */ +#pragma once + +#include +#include +#include +#include +#include +#include "IdGenOptions.h" + + +extern pthread_mutex_t ThreadMutex; + +typedef struct SnowFlakeWorker { + uint8_t Method; + uint64_t BaseTime; + uint32_t WorkerId; + uint8_t WorkerIdBitLength; + uint8_t SeqBitLength; + uint32_t MaxSeqNumber; + uint32_t MinSeqNumber; + uint32_t TopOverCostCount; + + uint8_t _TimestampShift; + uint32_t _CurrentSeqNumber; + int64_t _LastTimeTick; + int64_t _TurnBackTimeTick; + uint8_t _TurnBackIndex; + bool _IsOverCost; + uint32_t _OverCostCountInOneTerm; + uint32_t _GenCountInOneTerm; + uint32_t _TermIndex; + +} SnowFlakeWorker; + + +extern SnowFlakeWorker *NewSnowFlakeWorker(); + +extern uint64_t WorkerM1NextId(SnowFlakeWorker *worker); + +extern uint64_t GetCurrentTimeTick(SnowFlakeWorker *worker); + +extern uint64_t GetNextTimeTick(SnowFlakeWorker *worker); + +extern uint64_t GetCurrentTime(); + +extern uint64_t GetCurrentMicroTime(); + diff --git a/C/source/idgen/SnowWorkerM2.c b/C/source/idgen/SnowWorkerM2.c new file mode 100644 index 0000000..2718aac --- /dev/null +++ b/C/source/idgen/SnowWorkerM2.c @@ -0,0 +1,30 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 代码翻译:amuluowin + * 代码修订:yitter + * 开源地址:https://gitee.com/yitter/idgenerator + */ +#include +#include +#include +#include "SnowWorkerM2.h" + + +extern uint64_t WorkerM2NextId(SnowFlakeWorker *worker) { + pthread_mutex_lock(&ThreadMutex); + uint64_t currentTimeTick = GetCurrentTimeTick(worker); + if (worker->_LastTimeTick == currentTimeTick) { + worker->_CurrentSeqNumber = (++worker->_CurrentSeqNumber) & worker->MaxSeqNumber; + if (worker->_CurrentSeqNumber == 0) { + currentTimeTick = GetNextTimeTick(worker); + } + } else { + worker->_CurrentSeqNumber = worker->MinSeqNumber; + } + worker->_LastTimeTick = currentTimeTick; + uint64_t id = (uint64_t) ((currentTimeTick << worker->_TimestampShift) | + (worker->WorkerId << worker->SeqBitLength) | + worker->_CurrentSeqNumber); + pthread_mutex_unlock(&ThreadMutex); + return id; +} diff --git a/C/source/idgen/SnowWorkerM2.h b/C/source/idgen/SnowWorkerM2.h new file mode 100644 index 0000000..6109601 --- /dev/null +++ b/C/source/idgen/SnowWorkerM2.h @@ -0,0 +1,13 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 代码翻译:amuluowin + * 代码修订:yitter + * 开源地址:https://gitee.com/yitter/idgenerator + */ +#pragma once + +#include +#include "SnowWorkerM1.h" + + +extern uint64_t WorkerM2NextId(SnowFlakeWorker *worker); diff --git a/C/source/idgen/common.h b/C/source/idgen/common.h new file mode 100644 index 0000000..89522f2 --- /dev/null +++ b/C/source/idgen/common.h @@ -0,0 +1,15 @@ +// +// Created by zhouzj on 2021/3/28. +// +#pragma once + +#ifdef _WIN32 +#define TAP_CDECL __cdecl +#define TAP_STDCALL __stdcall +#define TAP_DLLEXPORT __declspec(dllexport) +#else +#define TAP_CDECL +#define TAP_STDCALL +#define TAP_DLLEXPORT +#endif + diff --git a/C/source/main.c b/C/source/main.c new file mode 100644 index 0000000..7ed607f --- /dev/null +++ b/C/source/main.c @@ -0,0 +1,67 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 代码翻译:amuluowin + * 代码修订:yitter + * 开源地址:https://gitee.com/yitter/idgenerator + */ +#include +#include +#include +#include +#include +#include +#include "idgen/SnowWorkerM1.h" +#include "idgen/IdGenerator.h" +#include "YitIdHelper.h" + + +const int GenIdCount = 50000; +const bool multiThread = false; +const int threadCount = 50; +const int method = 1; + +void RunMultiThread() { + //int64_t start = GetCurrentMicroTime(); + for (int i = 0; i < GenIdCount / threadCount; i++) { + int64_t id = NextId(); + printf("生成ID: %D\n", id); + } + + int64_t end = GetCurrentMicroTime(); + //printf("%s,total:%d μs\n", method == 1 ? "1" : "2", (end - start)); +} + +void RunSingle() { + int64_t start = GetCurrentMicroTime(); + for (int i = 0; i < GenIdCount; i++) { + int64_t id = NextId(); +// printf("生成ID: %ld\n", id); + } + + int64_t end = GetCurrentMicroTime(); + printf("%s,total:%d μs\n", method == 1 ? "1" : "2", (end - start)); +} + +int main() { + IdGeneratorOptions options = BuildIdGenOptions(1); + options.Method = method; + options.WorkerId = 1; + options.SeqBitLength = 6; + SetIdGenerator(options); + + pthread_t tid[threadCount]; + while (1) { + if (multiThread) { + for (int i = 0; i < threadCount; i++) { + if (pthread_create(&tid[i], NULL, (void *) RunMultiThread, NULL) != 0) { + printf("thread creation failed\n"); + exit(1); + } + } + } else { + RunSingle(); + } + + sleep(1); + } +} diff --git a/Go/README.md b/Go/README.md new file mode 100644 index 0000000..7a56931 --- /dev/null +++ b/Go/README.md @@ -0,0 +1,29 @@ +# idgenerator + +## Go + +1.SDKgo1.16 + +2. Go-Modules + +``` +go env -w GO111MODULE=on +go env -w GOPROXY=https://goproxy.cn,https://goproxy.io,direct +``` + + +## Goʾ +``` +var yid = idgen.YitIdHelper{} +fmt.Println(yid.NextId()) + +// Զ +var options = contract.NewIdGeneratorOptions(1) +//options.WorkerIdBitLength = 6 +//options.SeqBitLength = 6 +//options.TopOverCostCount = 2000 +//options.BaseTime = time.Date(2020, 2, 20, 2, 20, 2, 20, time.UTC).UnixNano() / 1e6 +yid.SetIdGenerator(options) + +``` + diff --git a/Go/source/contract/IIdGenerator.go b/Go/source/contract/IIdGenerator.go new file mode 100644 index 0000000..48c346f --- /dev/null +++ b/Go/source/contract/IIdGenerator.go @@ -0,0 +1,11 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 代码编辑:guoyahao + * 代码修订:yitter + * 开源地址:https://gitee.com/yitter/idgenerator + */ +package contract + +type IIdGenerator interface { + NewLong() uint64 +} diff --git a/Go/source/contract/ISnowWorker.go b/Go/source/contract/ISnowWorker.go new file mode 100644 index 0000000..5a98ad9 --- /dev/null +++ b/Go/source/contract/ISnowWorker.go @@ -0,0 +1,11 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 代码编辑:guoyahao + * 代码修订:yitter + * 开源地址:https://gitee.com/yitter/idgenerator + */ +package contract + +type ISnowWorker interface { + NextId() uint64 +} diff --git a/Go/source/contract/IdGeneratorException.go b/Go/source/contract/IdGeneratorException.go new file mode 100644 index 0000000..9b3cf05 --- /dev/null +++ b/Go/source/contract/IdGeneratorException.go @@ -0,0 +1,18 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 代码编辑:guoyahao + * 代码修订:yitter + * 开源地址:https://gitee.com/yitter/idgenerator + */ +package contract + +import "fmt" + +type IdGeneratorException struct { + message string + error error +} + +func (e IdGeneratorException) IdGeneratorException(message ...interface{}) { + fmt.Println(message) +} diff --git a/Go/source/contract/IdGeneratorOptions.go b/Go/source/contract/IdGeneratorOptions.go new file mode 100644 index 0000000..bd2afc2 --- /dev/null +++ b/Go/source/contract/IdGeneratorOptions.go @@ -0,0 +1,31 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 代码编辑:guoyahao + * 代码修订:yitter + * 开源地址:https://gitee.com/yitter/idgenerator + */ +package contract + +type IdGeneratorOptions struct { + Method uint16 // 雪花计算方法,(1-漂移算法|2-传统算法),默认1 + BaseTime int64 // 基础时间(ms单位),不能超过当前系统时间 + WorkerId uint16 // 机器码,与 WorkerIdBitLength 有关系 + WorkerIdBitLength byte // 机器码位长,范围:1-21(要求:序列数位长+机器码位长不超过22) + SeqBitLength byte // 序列数位长,范围:2-21(要求:序列数位长+机器码位长不超过22) + MaxSeqNumber uint32 // 最大序列数(含),(由SeqBitLength计算的最大值) + MinSeqNumber uint32 // 最小序列数(含),默认5,不小于1,不大于MaxSeqNumber + TopOverCostCount uint32 // 最大漂移次数(含),默认2000,推荐范围500-10000(与计算能力有关) +} + +func NewIdGeneratorOptions(workerId uint16) *IdGeneratorOptions { + return &IdGeneratorOptions{ + Method: 1, + WorkerId: workerId, + BaseTime: 1582136402000, + WorkerIdBitLength: 6, + SeqBitLength: 6, + MaxSeqNumber: 0, + MinSeqNumber: 5, + TopOverCostCount: 2000, + } +} diff --git a/Go/source/contract/OverCostActionArg.go b/Go/source/contract/OverCostActionArg.go new file mode 100644 index 0000000..e8bbeb1 --- /dev/null +++ b/Go/source/contract/OverCostActionArg.go @@ -0,0 +1,25 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 代码编辑:guoyahao + * 代码修订:yitter + * 开源地址:https://gitee.com/yitter/idgenerator + */ +package contract + +type OverCostActionArg struct { + ActionType int32 + TimeTick int64 + WorkerId uint16 + OverCostCountInOneTerm int32 + GenCountInOneTerm int32 + TermIndex int32 +} + +func (ocaa OverCostActionArg) OverCostActionArg(workerId uint16, timeTick int64, actionType int32, overCostCountInOneTerm int32, genCountWhenOverCost int32, index int32) { + ocaa.ActionType = actionType + ocaa.TimeTick = timeTick + ocaa.WorkerId = workerId + ocaa.OverCostCountInOneTerm = overCostCountInOneTerm + ocaa.GenCountInOneTerm = genCountWhenOverCost + ocaa.TermIndex = index +} diff --git a/Go/source/core/snowWorkerM1.go b/Go/source/core/snowWorkerM1.go new file mode 100644 index 0000000..b5fc7db --- /dev/null +++ b/Go/source/core/snowWorkerM1.go @@ -0,0 +1,208 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 代码编辑:guoyahao + * 代码修订:yitter + * 开源地址:https://gitee.com/yitter/idgenerator + */ +package core + +import ( + "sync" + "time" + "yitidgen/contract" +) + +type SnowWorkerM1 struct { + BaseTime int64 //基础时间 + WorkerId uint16 //机器码 + WorkerIdBitLength byte //机器码位长 + SeqBitLength byte //自增序列数位长 + MaxSeqNumber uint32 //最大序列数(含) + MinSeqNumber uint32 //最小序列数(含) + TopOverCostCount uint32 //最大漂移次数 + _TimestampShift byte + _CurrentSeqNumber uint32 + _LastTimeTick int64 + _TurnBackTimeTick int64 + _TurnBackIndex byte + _IsOverCost bool + _OverCostCountInOneTerm uint32 + _GenCountInOneTerm uint32 + _TermIndex uint32 + sync.Mutex +} + +func NewSnowWorkerM1(options *contract.IdGeneratorOptions) contract.ISnowWorker { + var workerIdBitLength byte + var seqBitLength byte + var maxSeqNumber uint32 + + var workerId = options.WorkerId + + if options.WorkerIdBitLength == 0 { + workerIdBitLength = 6 + } else { + workerIdBitLength = options.WorkerIdBitLength + } + if options.SeqBitLength == 0 { + seqBitLength = 6 + } else { + seqBitLength = options.SeqBitLength + } + if options.MaxSeqNumber > 0 { + maxSeqNumber = options.MaxSeqNumber + } else { + maxSeqNumber = (1 << seqBitLength) - 1 + } + var minSeqNumber = options.MinSeqNumber + var topOverCostCount = options.TopOverCostCount + + var baseTime int64 + if options.BaseTime != 0 { + baseTime = options.BaseTime + } else { + baseTime = 1582136402000 + } + timestampShift := (byte)(options.WorkerIdBitLength + options.SeqBitLength) + currentSeqNumber := options.MinSeqNumber + return &SnowWorkerM1{ + BaseTime: baseTime, + WorkerId: workerId, + WorkerIdBitLength: workerIdBitLength, + SeqBitLength: seqBitLength, + MaxSeqNumber: maxSeqNumber, + MinSeqNumber: minSeqNumber, + TopOverCostCount: topOverCostCount, + _TimestampShift: timestampShift, + _CurrentSeqNumber: currentSeqNumber} +} + +func (m1 *SnowWorkerM1) DoGenIdAction(arg *contract.OverCostActionArg) { + +} + +func (m1 *SnowWorkerM1) BeginOverCostAction(useTimeTick int64) { + +} + +func (m1 *SnowWorkerM1) EndOverCostAction(useTimeTick int64) { + if m1._TermIndex > 10000 { + m1._TermIndex = 0 + } +} + +func (m1 *SnowWorkerM1) BeginTurnBackAction(useTimeTick int64) { + +} + +func (m1 *SnowWorkerM1) EndTurnBackAction(useTimeTick int64) { + +} + +func (m1 *SnowWorkerM1) NextOverCostId() uint64 { + currentTimeTick := m1.GetCurrentTimeTick() + if currentTimeTick > m1._LastTimeTick { + m1.EndOverCostAction(currentTimeTick) + m1._LastTimeTick = currentTimeTick + m1._CurrentSeqNumber = m1.MinSeqNumber + m1._IsOverCost = false + m1._OverCostCountInOneTerm = 0 + m1._GenCountInOneTerm = 0 + return m1.CalcId(m1._LastTimeTick) + } + if m1._OverCostCountInOneTerm >= m1.TopOverCostCount { + m1.EndOverCostAction(currentTimeTick) + m1._LastTimeTick = m1.GetNextTimeTick() + m1._CurrentSeqNumber = m1.MinSeqNumber + m1._IsOverCost = false + m1._OverCostCountInOneTerm = 0 + m1._GenCountInOneTerm = 0 + return m1.CalcId(m1._LastTimeTick) + } + if m1._CurrentSeqNumber > m1.MaxSeqNumber { + m1._LastTimeTick++ + m1._CurrentSeqNumber = m1.MinSeqNumber + m1._IsOverCost = true + m1._OverCostCountInOneTerm++ + m1._GenCountInOneTerm++ + + return m1.CalcId(m1._LastTimeTick) + } + m1._GenCountInOneTerm++ + return m1.CalcId(m1._LastTimeTick) +} + +func (m1 *SnowWorkerM1) NextNormalId() uint64 { + currentTimeTick := m1.GetCurrentTimeTick() + if currentTimeTick < m1._LastTimeTick { + if m1._TurnBackTimeTick < 1 { + m1._TurnBackTimeTick = m1._LastTimeTick - 1 + m1._TurnBackIndex++ + // 每毫秒序列数的前5位是预留位,0用于手工新值,1-4是时间回拨次序 + // 最多4次回拨(防止回拨重叠) + if m1._TurnBackIndex > 4 { + m1._TurnBackIndex = 1 + } + m1.BeginTurnBackAction(m1._TurnBackTimeTick) + } + time.Sleep(time.Duration(10) * time.Millisecond) + return m1.CalcTurnBackId(m1._TurnBackTimeTick) + } + // 时间追平时,_TurnBackTimeTick清零 + if m1._TurnBackTimeTick > 0 { + m1.EndTurnBackAction(m1._TurnBackTimeTick) + m1._TurnBackTimeTick = 0 + } + if currentTimeTick > m1._LastTimeTick { + m1._LastTimeTick = currentTimeTick + m1._CurrentSeqNumber = m1.MinSeqNumber + return m1.CalcId(m1._LastTimeTick) + } + if m1._CurrentSeqNumber > m1.MaxSeqNumber { + m1.BeginOverCostAction(currentTimeTick) + m1._TermIndex++ + m1._LastTimeTick++ + m1._CurrentSeqNumber = m1.MinSeqNumber + m1._IsOverCost = true + m1._OverCostCountInOneTerm = 1 + m1._GenCountInOneTerm = 1 + + return m1.CalcId(m1._LastTimeTick) + } + return m1.CalcId(m1._LastTimeTick) +} + +func (m1 *SnowWorkerM1) CalcId(useTimeTick int64) uint64 { + result := uint64(useTimeTick< m2.MaxSeqNumber { + m2._CurrentSeqNumber = m2.MinSeqNumber + currentTimeTick = m2.GetNextTimeTick() + } + } else { + m2._CurrentSeqNumber = m2.MinSeqNumber + } + if currentTimeTick < m2._LastTimeTick { + fmt.Println("Time error for {0} milliseconds", strconv.FormatInt(m2._LastTimeTick-currentTimeTick, 10)) + } + m2._LastTimeTick = currentTimeTick + result := uint64((currentTimeTick << m2._TimestampShift)) + uint64(m2.WorkerId< time.Now().UnixNano()/1e6 { + panic("BaseTime error.") + } + + if options.SeqBitLength+options.WorkerIdBitLength > 22 { + panic("error:WorkerIdBitLength + SeqBitLength <= 22") + } + + maxWorkerIdNumber := uint16(1< maxWorkerIdNumber { + panic("WorkerId error. (range:[1, " + string(maxWorkerIdNumber) + "]") + } + + if options.SeqBitLength < 2 || options.SeqBitLength > 21 { + panic("SeqBitLength error. (range:[2, 21])") + } + + maxSeqNumber := uint32(1< maxSeqNumber { + panic("MaxSeqNumber error. (range:[1, " + string(maxSeqNumber) + "]") + } + + if options.MinSeqNumber > maxSeqNumber { + panic("MinSeqNumber error. (range:[1, " + string(maxSeqNumber) + "]") + } + + var snowWorker contract.ISnowWorker + + switch options.Method { + case 1: + snowWorker = core.NewSnowWorkerM1(options) + case 2: + snowWorker = core.NewSnowWorkerM2(options) + default: + snowWorker = core.NewSnowWorkerM1(options) + } + + if options.Method == 1 { + time.Sleep(time.Duration(500) * time.Microsecond) + } + return &DefaultIdGenerator{ + Options: options, + SnowWorker: snowWorker, + } +} + +func (dig DefaultIdGenerator) NewLong() uint64 { + return dig.SnowWorker.NextId() +} diff --git a/Go/source/gen/YitIdHelper.go b/Go/source/gen/YitIdHelper.go new file mode 100644 index 0000000..fc93df8 --- /dev/null +++ b/Go/source/gen/YitIdHelper.go @@ -0,0 +1,47 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 代码编辑:guoyahao + * 代码修订:yitter + * 开源地址:https://gitee.com/yitter/idgenerator + */ +package gen + +import ( + "sync" + "yitidgen/contract" +) + +var ins *YitIdHelper +var once sync.Once + +type YitIdHelper struct { + idGenInstance interface { + NewLong() uint64 + } +} + +func GetIns() *YitIdHelper { + once.Do(func() { + ins = &YitIdHelper{} + }) + return ins +} + +func (yih *YitIdHelper) GetIdGenInstance() interface{} { + return yih.idGenInstance +} + +func (yih *YitIdHelper) SetIdGenerator(options *contract.IdGeneratorOptions) { + yih.idGenInstance = NewDefaultIdGenerator(options) +} + +func (yih *YitIdHelper) NextId() uint64 { + once.Do(func() { + if yih.idGenInstance == nil { + options := contract.NewIdGeneratorOptions(1) + yih.idGenInstance = NewDefaultIdGenerator(options) + } + }) + + return yih.idGenInstance.NewLong() +} diff --git a/Go/source/go.mod b/Go/source/go.mod new file mode 100644 index 0000000..8eafd7d --- /dev/null +++ b/Go/source/go.mod @@ -0,0 +1 @@ +module "yitidgen" \ No newline at end of file diff --git a/Go/source/test/main.go b/Go/source/test/main.go new file mode 100644 index 0000000..2dbc1c7 --- /dev/null +++ b/Go/source/test/main.go @@ -0,0 +1,36 @@ +package main + +import ( + "fmt" + "time" + "yitidgen/contract" + "yitidgen/gen" +) + +func main() { + // 方法一:直接采用默认方法生成一个Id + var yid = gen.YitIdHelper{} + fmt.Println(yid.NextId()) + + // 方法二:自定义参数 + var options = contract.NewIdGeneratorOptions(1) + //options.WorkerIdBitLength = 6 + //options.SeqBitLength = 6 + //options.TopOverCostCount = 2000 + //options.BaseTime = time.Date(2020, 2, 20, 2, 20, 2, 20, time.UTC).UnixNano() / 1e6 + yid.SetIdGenerator(options) + + var times = 50000 + + for { + var begin = time.Now().UnixNano() / 1e6 + for i := 0; i < times; i++ { + yid.NextId() + } + var end = time.Now().UnixNano() / 1e6 + + fmt.Println(end - begin) + time.Sleep(time.Duration(1000) * time.Millisecond) + } + +} diff --git a/Java/README.md b/Java/README.md new file mode 100644 index 0000000..d664343 --- /dev/null +++ b/Java/README.md @@ -0,0 +1,28 @@ + +## л + +JDK 1.8+ + +## maven +``` + +``` + +## ʾ +``` +// ȫֳʼWorkerIdĬ2^16-1ʼȫֻһΣұã +IdGeneratorOptions options = new IdGeneratorOptions(); +options.WorkerId = 1; +YitIdHelper.setIdGenerator(options); + +// ʼԺ󣬾ͿҪĵط÷ID +long newId = YitIdHelper.nextId(); + +``` +DIܼɣԲο YitIdHelper ȥ IdGenerator 󣬱ʹ****ģʽ + + +## options Ĭֵ˵ + +οԴ룺/contract/IdGeneratorOptions.java + diff --git a/Java/source/.gitignore b/Java/source/.gitignore new file mode 100644 index 0000000..b551e8b --- /dev/null +++ b/Java/source/.gitignore @@ -0,0 +1,25 @@ +# Compiled class file +*.class +*.iml + +# Log file +*.log + +# BlueJ files +*.ctxt + +# Mobile Tools for Java (J2ME) +.mtj.tmp/ + +# Package Files # +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar +target/ + +# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml +hs_err_pid* diff --git a/Java/source/LICENSE b/Java/source/LICENSE new file mode 100644 index 0000000..261eeb9 --- /dev/null +++ b/Java/source/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/Java/source/pom.xml b/Java/source/pom.xml new file mode 100644 index 0000000..811f482 --- /dev/null +++ b/Java/source/pom.xml @@ -0,0 +1,93 @@ + + + 4.0.0 + + com.yitter + yitter.idgenerator + jar + 1.0.0 + + yitter.idgenerator + Shorter ID and faster generation with a new snowflake drift algorithm. The core is to shorten the ID length, but also can have a very high instantaneous concurrent processing capacity (50W/0.1s), and powerful configuration capacity. + + + + yitter + yitter + yitter@126.com + https://gitee.com/yitter/idgenerator + + + + + UTF-8 + UTF-8 + 1.8 + 1.8 + 1.8 + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + ${java.version} + ${java.version} + UTF-8 + + + + org.apache.maven.plugins + maven-jar-plugin + 3.1.0 + + + org.apache.maven.plugins + maven-surefire-plugin + + true + + + + + + + ${project.basedir} + META-INF + + LICENSE + NOTICE + + + + src/main/resources + true + + ** + + + + + + src/test/resources + + ** + + + + + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + + + + \ No newline at end of file diff --git a/Java/source/src/main/java/com/yitter/contract/IIdGenerator.java b/Java/source/src/main/java/com/yitter/contract/IIdGenerator.java new file mode 100644 index 0000000..e0c28d5 --- /dev/null +++ b/Java/source/src/main/java/com/yitter/contract/IIdGenerator.java @@ -0,0 +1,9 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +package com.yitter.contract; + +public interface IIdGenerator { + long newLong() throws IdGeneratorException; +} diff --git a/Java/source/src/main/java/com/yitter/contract/ISnowWorker.java b/Java/source/src/main/java/com/yitter/contract/ISnowWorker.java new file mode 100644 index 0000000..4ba7b67 --- /dev/null +++ b/Java/source/src/main/java/com/yitter/contract/ISnowWorker.java @@ -0,0 +1,9 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +package com.yitter.contract; + +public interface ISnowWorker { + long nextId() throws IdGeneratorException; +} diff --git a/Java/source/src/main/java/com/yitter/contract/IdGeneratorException.java b/Java/source/src/main/java/com/yitter/contract/IdGeneratorException.java new file mode 100644 index 0000000..d3cb02e --- /dev/null +++ b/Java/source/src/main/java/com/yitter/contract/IdGeneratorException.java @@ -0,0 +1,29 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +package com.yitter.contract; + +public class IdGeneratorException extends RuntimeException { + + public IdGeneratorException() { + super(); + } + + public IdGeneratorException(String message) { + super(message); + } + + public IdGeneratorException(Throwable cause) { + super(cause); + } + + public IdGeneratorException(String message, Throwable cause) { + super(message, cause); + } + + public IdGeneratorException(String msgFormat, Object... args) { + super(String.format(msgFormat, args)); + } + +} diff --git a/Java/source/src/main/java/com/yitter/contract/IdGeneratorOptions.java b/Java/source/src/main/java/com/yitter/contract/IdGeneratorOptions.java new file mode 100644 index 0000000..2d1dfbb --- /dev/null +++ b/Java/source/src/main/java/com/yitter/contract/IdGeneratorOptions.java @@ -0,0 +1,71 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +package com.yitter.contract; + +/** + * 雪花算法使用的参数 + * 此处代码不采用 get/set 那种冗长的写法 + */ +public class IdGeneratorOptions { + + /** + * 雪花计算方法 + * (1-漂移算法|2-传统算法),默认1 + */ + public short Method = 1; + + /** + * 基础时间(ms单位) + * 不能超过当前系统时间 + */ + public long BaseTime = 1582136402000L; + + /** + * 机器码,必须由外部系统设置 + * 与 WorkerIdBitLength 有关系 + * (short类型,最大值32766,如果有更高要求,请修改数据类型,或联系作者) + */ + public short WorkerId = 0; + + /** + * 机器码位长 + * 范围:1-21(要求:序列数位长+机器码位长不超过22)。 + * 建议范围:6-12。 + */ + public byte WorkerIdBitLength = 6; + + /** + * 序列数位长 + * 范围:2-21(要求:序列数位长+机器码位长不超过22)。 + * 建议范围:6-14。 + */ + public byte SeqBitLength = 6; + + /** + * 最大序列数(含) + * (由SeqBitLength计算的最大值) + */ + public short MaxSeqNumber = 0; + + /** + * 最小序列数(含) + * 默认5,不小于1,不大于MaxSeqNumber + */ + public short MinSeqNumber = 5; + + /** + * 最大漂移次数(含) + * 默认2000,推荐范围500-10000(与计算能力有关) + */ + public short TopOverCostCount = 2000; + + public IdGeneratorOptions() { + + } + + public IdGeneratorOptions(short workerId) { + WorkerId = workerId; + } +} diff --git a/Java/source/src/main/java/com/yitter/contract/OverCostActionArg.java b/Java/source/src/main/java/com/yitter/contract/OverCostActionArg.java new file mode 100644 index 0000000..8192eb0 --- /dev/null +++ b/Java/source/src/main/java/com/yitter/contract/OverCostActionArg.java @@ -0,0 +1,51 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +package com.yitter.contract; + +/** + * Id生成时回调参数 + */ +public class OverCostActionArg { + + /** + * 事件类型 + * 1-开始,2-结束,8-漂移 + */ + public int ActionType = 0; + + /** + * 时间戳 + */ + public long TimeTick = 0; + + /** + * 机器码 + */ + public short WorkerId = 0; + + /** + * + */ + public int OverCostCountInOneTerm = 0; + + /** + * 漂移期间生产ID个数 + */ + public int GenCountInOneTerm = 0; + + /** + * 漂移周期 + */ + public int TermIndex = 0; + + public OverCostActionArg(short workerId, long timeTick, int actionType, int overCostCountInOneTerm, int genCountWhenOverCost, int index) { + ActionType = actionType; + TimeTick = timeTick; + WorkerId = workerId; + OverCostCountInOneTerm = overCostCountInOneTerm; + GenCountInOneTerm = genCountWhenOverCost; + TermIndex = index; + } +} diff --git a/Java/source/src/main/java/com/yitter/core/SnowWorkerM1.java b/Java/source/src/main/java/com/yitter/core/SnowWorkerM1.java new file mode 100644 index 0000000..d793c43 --- /dev/null +++ b/Java/source/src/main/java/com/yitter/core/SnowWorkerM1.java @@ -0,0 +1,261 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +package com.yitter.core; + +import com.yitter.contract.ISnowWorker; +import com.yitter.contract.IdGeneratorException; +import com.yitter.contract.IdGeneratorOptions; +import com.yitter.contract.OverCostActionArg; + +public class SnowWorkerM1 implements ISnowWorker { + + /** + * 基础时间 + */ + protected final long BaseTime; + + /** + * 机器码 + */ + protected final short WorkerId; + + /** + * 机器码位长 + */ + protected final byte WorkerIdBitLength; + + /** + * 自增序列数位长 + */ + protected final byte SeqBitLength; + + /** + * 最大序列数(含) + */ + protected final int MaxSeqNumber; + + /** + * 最小序列数(含) + */ + protected final short MinSeqNumber; + + /** + * 最大漂移次数 + */ + protected final int TopOverCostCount; + + protected final byte _TimestampShift; + protected final static byte[] _SyncLock = new byte[0]; + + protected short _CurrentSeqNumber; + protected long _LastTimeTick = -1L; + protected long _TurnBackTimeTick = -1L; + protected byte _TurnBackIndex = 0; + + protected boolean _IsOverCost = false; + protected int _OverCostCountInOneTerm = 0; + protected int _GenCountInOneTerm = 0; + protected int _TermIndex = 0; + + public SnowWorkerM1(IdGeneratorOptions options) { + WorkerId = options.WorkerId; + WorkerIdBitLength = options.WorkerIdBitLength == 0 ? 6 : options.WorkerIdBitLength; + SeqBitLength = options.SeqBitLength == 0 ? 6 : options.SeqBitLength; + MaxSeqNumber = options.MaxSeqNumber > 0 ? options.MaxSeqNumber : (int) Math.pow(2, SeqBitLength) - 1; + MinSeqNumber = options.MinSeqNumber; + TopOverCostCount = options.TopOverCostCount; + BaseTime = options.BaseTime != 0 ? options.BaseTime : 1582136402000L; + _TimestampShift = (byte) (WorkerIdBitLength + SeqBitLength); + _CurrentSeqNumber = options.MinSeqNumber; + } + + private void DoGenIdAction(OverCostActionArg arg) { + + } + + private void BeginOverCostAction(long useTimeTick) { +// if (GenAction == null) { +// return; +// } +// +// DoGenIdAction(new OverCostActionArg( +// WorkerId, +// useTimeTick, +// 1, +// _OverCostCountInOneTerm, +// _GenCountInOneTerm, +// _TermIndex)); + } + + private void EndOverCostAction(long useTimeTick) { + if (_TermIndex > 10000) { + _TermIndex = 0; + } +// +// if (GenAction == null) { +// return; +// } +// +// DoGenIdAction(new OverCostActionArg( +// WorkerId, +// useTimeTick, +// 2, +// _OverCostCountInOneTerm, +// _GenCountInOneTerm, +// _TermIndex)); + } + + private void BeginTurnBackAction(long useTimeTick) { +// if (GenAction == null) { +// return; +// } +// +// DoGenIdAction(new OverCostActionArg( +// WorkerId, +// useTimeTick, +// 8, +// _OverCostCountInOneTerm, +// _GenCountInOneTerm, +// _TermIndex)); + } + + private void EndTurnBackAction(long useTimeTick) { + + } + + private long NextOverCostId() { + long currentTimeTick = GetCurrentTimeTick(); + + if (currentTimeTick > _LastTimeTick) { + EndOverCostAction(currentTimeTick); + + _LastTimeTick = currentTimeTick; + _CurrentSeqNumber = MinSeqNumber; + _IsOverCost = false; + _OverCostCountInOneTerm = 0; + _GenCountInOneTerm = 0; + + return CalcId(_LastTimeTick); + } + + if (_OverCostCountInOneTerm >= TopOverCostCount) { + EndOverCostAction(currentTimeTick); + + _LastTimeTick = GetNextTimeTick(); + _CurrentSeqNumber = MinSeqNumber; + _IsOverCost = false; + _OverCostCountInOneTerm = 0; + _GenCountInOneTerm = 0; + + return CalcId(_LastTimeTick); + } + + if (_CurrentSeqNumber > MaxSeqNumber) { + _LastTimeTick++; + _CurrentSeqNumber = MinSeqNumber; + _IsOverCost = true; + _OverCostCountInOneTerm++; + _GenCountInOneTerm++; + + return CalcId(_LastTimeTick); + } + + _GenCountInOneTerm++; + return CalcId(_LastTimeTick); + } + + private long NextNormalId() throws IdGeneratorException { + long currentTimeTick = GetCurrentTimeTick(); + + if (currentTimeTick < _LastTimeTick) { + if (_TurnBackTimeTick < 1) { + _TurnBackTimeTick = _LastTimeTick - 1; + _TurnBackIndex++; + + // 每毫秒序列数的前5位是预留位,0用于手工新值,1-4是时间回拨次序 + // 最多4次回拨(防止回拨重叠) + if (_TurnBackIndex > 4) { + _TurnBackIndex = 1; + } + BeginTurnBackAction(_TurnBackTimeTick); + } + + try { + Thread.sleep(10); + } catch (InterruptedException e) { + e.printStackTrace(); + } + return CalcTurnBackId(_TurnBackTimeTick); + } + + // 时间追平时,_TurnBackTimeTick清零 + if (_TurnBackTimeTick > 0) { + EndTurnBackAction(_TurnBackTimeTick); + _TurnBackTimeTick = 0; + } + + if (currentTimeTick > _LastTimeTick) { + _LastTimeTick = currentTimeTick; + _CurrentSeqNumber = MinSeqNumber; + + return CalcId(_LastTimeTick); + } + + if (_CurrentSeqNumber > MaxSeqNumber) { + BeginOverCostAction(currentTimeTick); + + _TermIndex++; + _LastTimeTick++; + _CurrentSeqNumber = MinSeqNumber; + _IsOverCost = true; + _OverCostCountInOneTerm = 1; + _GenCountInOneTerm = 1; + + return CalcId(_LastTimeTick); + } + + return CalcId(_LastTimeTick); + } + + private long CalcId(long useTimeTick) { + long result = ((useTimeTick << _TimestampShift) + + ((long) WorkerId << SeqBitLength) + + (int) _CurrentSeqNumber); + + _CurrentSeqNumber++; + return result; + } + + private long CalcTurnBackId(long useTimeTick) { + long result = ((useTimeTick << _TimestampShift) + + ((long) WorkerId << SeqBitLength) + _TurnBackIndex); + + _TurnBackTimeTick--; + return result; + } + + protected long GetCurrentTimeTick() { + long millis = System.currentTimeMillis(); + return millis - BaseTime; + } + + protected long GetNextTimeTick() { + long tempTimeTicker = GetCurrentTimeTick(); + + while (tempTimeTicker <= _LastTimeTick) { + tempTimeTicker = GetCurrentTimeTick(); + } + + return tempTimeTicker; + } + + @Override + public long nextId() { + synchronized (_SyncLock) { + return _IsOverCost ? NextOverCostId() : NextNormalId(); + } + } +} + diff --git a/Java/source/src/main/java/com/yitter/core/SnowWorkerM2.java b/Java/source/src/main/java/com/yitter/core/SnowWorkerM2.java new file mode 100644 index 0000000..eb2ffe3 --- /dev/null +++ b/Java/source/src/main/java/com/yitter/core/SnowWorkerM2.java @@ -0,0 +1,41 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +package com.yitter.core; + +import com.yitter.contract.IdGeneratorException; +import com.yitter.contract.IdGeneratorOptions; + +public class SnowWorkerM2 extends SnowWorkerM1 { + + public SnowWorkerM2(IdGeneratorOptions options) { + super(options); + } + + @Override + public long nextId() { + synchronized (_SyncLock) { + long currentTimeTick = GetCurrentTimeTick(); + + if (_LastTimeTick == currentTimeTick) { + if (_CurrentSeqNumber++ > MaxSeqNumber) { + _CurrentSeqNumber = MinSeqNumber; + currentTimeTick = GetNextTimeTick(); + } + } else { + _CurrentSeqNumber = MinSeqNumber; + } + + if (currentTimeTick < _LastTimeTick) { + throw new IdGeneratorException("Time error for {0} milliseconds", _LastTimeTick - currentTimeTick); + } + + _LastTimeTick = currentTimeTick; + long result = ((currentTimeTick << _TimestampShift) + ((long) WorkerId << SeqBitLength) + (int) _CurrentSeqNumber); + + return result; + } + + } +} diff --git a/Java/source/src/main/java/com/yitter/idgen/DefaultIdGenerator.java b/Java/source/src/main/java/com/yitter/idgen/DefaultIdGenerator.java new file mode 100644 index 0000000..9443501 --- /dev/null +++ b/Java/source/src/main/java/com/yitter/idgen/DefaultIdGenerator.java @@ -0,0 +1,79 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +package com.yitter.idgen; + +import com.yitter.contract.ISnowWorker; +import com.yitter.contract.IdGeneratorException; +import com.yitter.contract.IdGeneratorOptions; +import com.yitter.contract.IIdGenerator; +import com.yitter.core.SnowWorkerM1; +import com.yitter.core.SnowWorkerM2; + + +public class DefaultIdGenerator implements IIdGenerator { + + private static ISnowWorker _SnowWorker = null; + + public DefaultIdGenerator(IdGeneratorOptions options) throws IdGeneratorException { + if (options == null) { + throw new IdGeneratorException("options error."); + } + + if (options.BaseTime < 315504000000L || options.BaseTime > System.currentTimeMillis()) { + throw new IdGeneratorException("BaseTime error."); + } + + if (options.WorkerIdBitLength <= 0) { + throw new IdGeneratorException("WorkerIdBitLength error.(range:[1, 21])"); + } + if (options.SeqBitLength + options.WorkerIdBitLength > 22) { + throw new IdGeneratorException("error:WorkerIdBitLength + SeqBitLength <= 22"); + } + + int maxWorkerIdNumber = (1 << options.WorkerIdBitLength) - 1; + if (options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber) { + throw new IdGeneratorException("WorkerId error. (range:[0, " + (maxWorkerIdNumber > 0 ? maxWorkerIdNumber : 63) + "]"); + } + + if (options.SeqBitLength < 2 || options.SeqBitLength > 21) { + throw new IdGeneratorException("SeqBitLength error. (range:[2, 21])"); + } + + int maxSeqNumber = (1 << options.SeqBitLength) - 1; + if (options.MaxSeqNumber < 0 || options.MaxSeqNumber > maxSeqNumber) { + throw new IdGeneratorException("MaxSeqNumber error. (range:[1, " + maxSeqNumber + "]"); + } + + int maxValue = maxSeqNumber; + if (options.MinSeqNumber < 1 || options.MinSeqNumber > maxValue) { + throw new IdGeneratorException("MinSeqNumber error. (range:[1, " + maxValue + "]"); + } + + switch (options.Method) { + case 1: + _SnowWorker = new SnowWorkerM1(options); + break; + case 2: + _SnowWorker = new SnowWorkerM2(options); + break; + default: + _SnowWorker = new SnowWorkerM1(options); + break; + } + + if (options.Method == 1) { + try { + Thread.sleep(500); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + } + + @Override + public long newLong() { + return _SnowWorker.nextId(); + } +} diff --git a/Java/source/src/main/java/com/yitter/idgen/YitIdHelper.java b/Java/source/src/main/java/com/yitter/idgen/YitIdHelper.java new file mode 100644 index 0000000..45d28ec --- /dev/null +++ b/Java/source/src/main/java/com/yitter/idgen/YitIdHelper.java @@ -0,0 +1,45 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +package com.yitter.idgen; + +import com.yitter.contract.IdGeneratorException; +import com.yitter.contract.IdGeneratorOptions; +import com.yitter.contract.IIdGenerator; + +/** + * 这是一个调用的例子,默认情况下,单机集成者可以直接使用 nextId()。 + */ +public class YitIdHelper { + + private static IIdGenerator idGenInstance = null; + + public static IIdGenerator getIdGenInstance() { + return idGenInstance; + } + + + /** + * 设置参数,建议程序初始化时执行一次 + * + * @param options + */ + public static void setIdGenerator(IdGeneratorOptions options) throws IdGeneratorException { + idGenInstance = new DefaultIdGenerator(options); + } + + /** + * 生成新的Id + * 调用本方法前,请确保调用了 SetIdGenerator 方法做初始化。 + * + * @return + */ + public static long nextId() throws IdGeneratorException { + if (idGenInstance == null) { + idGenInstance = new DefaultIdGenerator(new IdGeneratorOptions((short) 1)); + } + + return idGenInstance.newLong(); + } +} diff --git a/Java/source/src/main/java/com/yitter/test/GenTest.java b/Java/source/src/main/java/com/yitter/test/GenTest.java new file mode 100644 index 0000000..6a4647c --- /dev/null +++ b/Java/source/src/main/java/com/yitter/test/GenTest.java @@ -0,0 +1,38 @@ +package com.yitter.test; + +import com.yitter.contract.IIdGenerator; + +import java.util.HashSet; +import java.util.Set; + +public class GenTest { + + private IIdGenerator IdGen; + private int GenIdCount; + private int WorkerId; + private Set IdSet = new HashSet(); + + public GenTest(IIdGenerator idGen, int genIdCount, int workerId) { + GenIdCount = genIdCount; + IdGen = idGen; + WorkerId = workerId; + } + + public void GenStart() { + long start = System.currentTimeMillis(); + long id = 0; + + for (int i = 0; i < GenIdCount; i++) { + id = IdGen.newLong(); + // IdSet.add(id); + } + + long end = System.currentTimeMillis(); + long time = end - start; + + System.out.println(id); + System.out.println("++++++++++++++++++++++++++++++++++++++++WorkerId: " + + WorkerId + ", total: " + time + " ms"); + + } +} diff --git a/Java/source/src/main/java/com/yitter/test/StartUp.java b/Java/source/src/main/java/com/yitter/test/StartUp.java new file mode 100644 index 0000000..6f5e575 --- /dev/null +++ b/Java/source/src/main/java/com/yitter/test/StartUp.java @@ -0,0 +1,55 @@ +package com.yitter.test; + +import com.yitter.contract.IdGeneratorOptions; +import com.yitter.contract.IIdGenerator; +import com.yitter.idgen.DefaultIdGenerator; +import com.yitter.idgen.YitIdHelper; + +public class StartUp { + + /** + * 测试结果: + * (1):1W并发,方法 1只要 1ms.而方法 2 要 180ms。 + * (2):5W并发,方法 1只要 3ms.而方法 2 要 900ms。 + * [不同CPU可能结果有差异,但相对大小不变] + * 默认配置下,最佳性能是5W/s-8W/s + */ + final static int genIdCount = 50000; + + //1-漂移算法,2-传统算法 + final static short method = 1; + + + public static void main(String[] args) { + IdGeneratorOptions options = new IdGeneratorOptions(); +// options.WorkerIdBitLength = 6; +// options.SeqBitLength = 6; +// options.TopOverCostCount = 2000; + // options.MinSeqNumber = 5; + // options.MaxSeqNumber = 200; + + options.Method = method; + options.BaseTime = 1582206693000L; + options.WorkerId = 1; + + IIdGenerator idGen = new DefaultIdGenerator(options); + GenTest genTest = new GenTest(idGen, genIdCount, options.WorkerId); + + // 首先测试一下 IdHelper 方法,获取单个Id + YitIdHelper.setIdGenerator(options); + long newId = YitIdHelper.nextId(); + System.out.println("====================================="); + System.out.println("这是用方法 " + method + " 生成的 Id:" + newId); + + // 然后循环测试一下,看看并发请求时的耗时情况 + try { + while (true) { + genTest.GenStart(); + Thread.sleep(1000); // 每隔1秒执行一次GenStart + System.out.println("Hello World! Java"); + } + } catch (InterruptedException e) { + e.printStackTrace(); + } + } +} diff --git a/PHP/README.md b/PHP/README.md new file mode 100644 index 0000000..aab2eef --- /dev/null +++ b/PHP/README.md @@ -0,0 +1,4 @@ +# idgenerator + +something is going on. + diff --git a/README.en.md b/README.en.md new file mode 100644 index 0000000..e1e5bec --- /dev/null +++ b/README.en.md @@ -0,0 +1,37 @@ +# idgenerator + +#### Description +用一种全新的雪花漂移算法,让ID更短、生成速度更快,0.1秒可生成50万个ID。 + + +#### Software Architecture +Software architecture description + +#### Installation + +1. xxxx +2. xxxx +3. xxxx + +#### Instructions + +1. xxxx +2. xxxx +3. xxxx + +#### Contribution + +1. Fork the repository +2. Create Feat_xxx branch +3. Commit your code +4. Create Pull Request + + +#### Gitee Feature + +1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md +2. Gitee blog [blog.gitee.com](https://blog.gitee.com) +3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) +4. The most valuable open source project [GVP](https://gitee.com/gvp) +5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) +6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git a/README.md b/README.md new file mode 100644 index 0000000..b78c047 --- /dev/null +++ b/README.md @@ -0,0 +1,204 @@ +# IdGenerator SnowFlake 雪花算法 原生多语言版本 顶尖优化 超强效能 + +## 介绍 + +1.一个全新的雪花漂移算法,使生成的ID更短、速度更快。 + +2.核心在于缩短ID长度的同时,还能拥有极高瞬时并发处理量(保守值 50W/0.1s)。 + +3.原生支持 C#/Java/Go/Rust/C 等语言,并由 Rust 提供 PHP、Python、Node.js、Ruby 等语言多线程安全调用库(FFI)。 + + +## 技术支持 + +开源地址:https://gitee.com/yitter/idgenerator + +QQ群:646049993 + +## 需求来源 + +1.作为架构设计的你,想要解决数据库主键唯一的问题,特别是在分布式系统多数据库的时候。 + +2.你希望这个主键是用最少的存储空间,索引速度更快,Select、Insert 和 Update 更迅速。 + +3.你要考虑在分库分表(合库合表)时,主键值可直接使用,并能反映业务时序。 + +4.如果这样的主键值太长,超过前端 JS Number 类型最大值,须把 Long 型转换为 String 型,你会觉得有点沮丧。 + +5.哪怕 Guid 能自增,但占用空间大,索引速度慢,所以你也不想用它。 + +6.你的应用实例可能超过50个,每个并发请求可达10W/s。 + +7.在容器环境部署应用(水平扩展、自动伸缩)。 + +8.你可不想 Id 生成器依赖 redis 的自增操作。 + +9.你希望系统运行 100 年以上。 + + +## 传统算法问题 + +1.生成的ID太长。 + +2.瞬时并发量不够。 + +3.不能解决时间回拨问题。 + +4.不支持后补生成前序ID。 + +5.依赖外部存储系统。 + + +## 新算法特点 + +1.整形数字,随时间单调递增(不一定连续),长度更短,用50年都不会超过 js Number类型最大值。(默认配置 WorkerId 是6bit,自增数是6bit) + +2.速度更快,是传统雪花算法的2-5倍,0.1秒可生成50万个。(i7笔记本,默认算法配置6bit+6bit) + +3.支持时间回拨处理。比如服务器时间回拨1秒,本算法能自动适应生成临界时间的唯一ID。 + +4.支持手工插入新ID。当业务需要在历史时间生成新ID时,用本算法的预留位能生成5000个每秒。 + +5.漂移时能外发通知事件。让调用方确切知道算法漂移记录,Log并发调用量。 + +6.不依赖任何外部缓存和数据库。(当然 WorkerId 须由外部指定) + + +## 性能数据 +(参数:10位自增序列,1000次漂移最大值) +| 连续请求量 | 5K | 5W | 50W | +| ---- | ---- | ---- | ---- | +| 传统雪花算法 | 0.0045s | 0.053s | 0.556s | +| 雪花漂移算法 | 0.0015s | 0.012s | 0.113s | + +## 效果 + +1.js Number 类型最大数值:9007199254740992,本算法在保持并发性能(5W+/0.01s)和最大64个 WorkerId(6bit)的同时,能用70年才到 js Number Max 值。 + +2.增加WorkerId位数到8bit(256节点)时,15年达到 js Number Max 值。 + +3.极致性能:500W/s~3000W/s。 + +4.所有测试数据均基于8代低压i7计算。 + +#### 生成的ID + +默认配置: +``` +WorkerIdBitLength = 6 +SeqBitLength = 6 +``` + +ID示例(基于默认配置): +``` +129053495681099 (本算法运行1年) +387750301904971 (运行3年) +646093214093387 (运行5年) +1292658282840139 (运行10年) +9007199254740992 (js Number 最大值) +165399880288699493 (普通雪花算法生成的ID) +``` +本算法生成的 ID 值,是 js Number 最大值的 1%-10%,是普通雪花算法值的千分之一,而计算能力却超过普通雪花算法。 + + +## 适用范围 + +1.小型、中型、大型需要全局唯一Id(不用Guid)的项目。 + +2.分布式项目。 + +3.不想将 Long 型转 String 给前端用的项目。(若前端支持bigint,则可不转类型) + + +## 如何处理时间回拨 +1.当发生系统时间回拨时,算法采用过去时序的预留序数生成新的ID。 + +2.默认每秒生成100个(速度可调整)。 + +3.回拨生成的ID序号,默认靠前,也可以调整为靠后。 + +4.允许时间回拨至本算法预设基数(参数可调)。 + + +## 能用多久 + +1.在默认配置下,ID可用 71000 年不重复。 + +2.在支持 1024 个工作节点时,ID可用 4480 年不重复。 + +3.在支持 4096 个工作节点时,ID可用 1120 年不重复。 + +4.以上所有工作节点,均拥有 50W/0.1s 瞬时处理速度。 + +#### 默认配置 + +1.WorkerIdBitLength=6,能支持64个 WorkerId,编号0~63。 + +2.可通过减少 WorkerIdBitLength 到1~4(为4时最大支持WorkerId为2^4=16个),以减少Id长度。 + +3.SeqBitLength=6,能支持每秒并发5W请求时,平均处理速度不超过 0.005 s。(不同语言略有差别,最高性能不超过0.002s,平均不超过0.005s) + +4.可通过增加 SeqBitLength,支持更高的每秒并发数。默认配置能很高效地支持每秒 5W 并发请求,若要求更高,可适当增加 SeqBitLength 到 8~16,但这将增加Id长度。 + + +## ★★集成建议★★ + +#### 常规集成 + +1.用单例模式调用。外部集成方使用更多的实例并行调用本算法,不会增加ID产出效能,因为本算法采用单线程模式生成ID。 + +2.指定唯一的 WorkerId。必须由外部系统确保 WorkerId 的全局唯一性,并赋值给本算法入口方法。 + +3.单机多实例部署时使用不同 WorkerId。并非所有实现都支持跨进程的并发唯一,保险起见,在同一主机上部署多应用实例时,请确保各 WorkerId 唯一。 + +4.异常处理。算法会抛出所有 Exception,外部系统应 catch 异常并做好应对处理,以免引发更大的系统崩溃。 + +5.认真理解 IdGeneratorOptions 的定义,这对集成和使用本算法有帮助。 + +6.使用雪花漂移算法。虽然代码里包含了传统雪花算法的定义,并且你可以在入口处指定(Method=2)来启用传统算法,但仍建议你使用雪花漂移算法(Method=1,默认的),毕竟它具有更好的伸缩力和更高的性能。 + +7.不要修改核心算法。本算法内部参数较多,逻辑较为复杂,在你尚未掌握核心逻辑时,请勿尝试修改核心代码且用于生产环境,除非通过大量细致、科学的测试验证。 + + +#### 大型分布式集成 + +1.可增加 WorkerIdBitLength 到最大20,支持 1,048,576 个节点,且不影响上述并发性能。[算法支持] + +2.采用中心化 IdGenerator 集群,生成可用 Id 列表,存入 Redis 队列供节点消费。此时64个中心化节点数足够大型互联网项目使用。[需集成方扩展实现] + +3.以上2条二选一即可,采用方法2一般是因为不想增加最终 ID 长度,但节点数超过64个。 + +4.任何加大 WorkerIdBitLength 或 SeqBitLength 的设置,都可能会增加 ID 的长度。 + +#### 配置变更 + +配置变更指是系统运行一段时间后,再变更运行参数(IdGeneratorOptions选项值),请注意: + +1.最重要的一条原则是:BaseTime **只能往前**(比老值更小、距离现在更远)赋值,原因是往后赋值极大可能产生相同的时间戳。[**不推荐**在系统运行之后调整 BaseTime] + +2.任何时候增加 WorkerIdBitLength 或 SeqBitLength,都是可以的,但是慎用 “减小”的操作,因为这可能导致在未来某天生成的 ID 与过去老配置时相同。[允许在系统运行之后**增加**任何一个 BitLength 值] + +3.如果必须减小 WorkerIdBitLength 或 SeqBitLength 其中的一项,一定要满足一个条件:新的两个 BitLength 之和要大于 老的值之和。[**不推荐**在运行之后缩小任何一个 BitLength 值] + +4.上述3条规则,并未在本算法内做逻辑控制,集成方应根据上述规则做好影响评估,确认无误后,再实施配置变更。 + + +## 代码示例 + +C#:[查看示例][1] + +Java:[查看示例][2] + +Go:[查看示例][3] + +Rust:[查看示例][4] + + +即将推出 PHP 扩展调用版本。 + + + +[1]: https://gitee.com/yitter/idgenerator/tree/master/C%23.NET +[2]: https://gitee.com/yitter/idgenerator/tree/master/Java +[3]: https://gitee.com/yitter/idgenerator/tree/master/Go +[4]: https://gitee.com/yitter/idgenerator/tree/master/Rust diff --git a/Rust/README.md b/Rust/README.md new file mode 100644 index 0000000..9fc87d8 --- /dev/null +++ b/Rust/README.md @@ -0,0 +1,5 @@ +# idgenerator + +Done. + + diff --git a/Rust/source/.gitignore b/Rust/source/.gitignore new file mode 100644 index 0000000..2db4c9f --- /dev/null +++ b/Rust/source/.gitignore @@ -0,0 +1,257 @@ +## Ignore Visual Studio temporary files, build results, and +## files generated by popular Visual Studio add-ons. + +# User-specific files +*.suo +*.user +*.userosscache +*.sln.docstates +*.editorconfig + +# User-specific files (MonoDevelop/Xamarin Studio) +*.userprefs + +# Build results +[Dd]ebug/ +[Dd]ebugPublic/ +[Rr]elease/ +[Rr]eleases/ +x64/ +x86/ +bld/ +[Bb]in/ +[Oo]bj/ +[Ll]og/ + +# Visual Studio 2015 cache/options directory +**/.vs/ +# Uncomment if you have tasks that create the project's static files in wwwroot +#wwwroot/ + +# MSTest test Results +[Tt]est[Rr]esult*/ +[Bb]uild[Ll]og.* + +# NUNIT +*.VisualState.xml +TestResult.xml + +# Build Results of an ATL Project +[Dd]ebugPS/ +[Rr]eleasePS/ + +# DNX +project.lock.json +artifacts/ + +*_i.c +*_p.c +*_i.h +*.ilk +*.meta +*.obj +*.pch +*.pdb +*.pgc +*.pgd +*.rsp +*.sbr +*.tlb +*.tli +*.tlh +*.tmp +*.tmp_proj +*.log +*.vspscc +*.vssscc +.builds +*.pidb +*.svclog +*.scc + +# Chutzpah Test files +_Chutzpah* + +# Visual C++ cache files +ipch/ +*.aps +*.ncb +*.opendb +*.opensdf +*.sdf +*.cachefile +*.VC.db +*.VC.VC.opendb + +# Visual Studio profiler +*.psess +*.vsp +*.vspx +*.sap + +# TFS 2012 Local Workspace +$tf/ + +# Guidance Automation Toolkit +*.gpState + +# ReSharper is a .NET coding add-in +_ReSharper*/ +*.[Rr]e[Ss]harper +*.DotSettings.user + +# JustCode is a .NET coding add-in +.JustCode + +# TeamCity is a build add-in +_TeamCity* + +# DotCover is a Code Coverage Tool +*.dotCover + +# NCrunch +_NCrunch_* +.*crunch*.local.xml +nCrunchTemp_* + +# MightyMoose +*.mm.* +AutoTest.Net/ + +# Web workbench (sass) +.sass-cache/ + +# Installshield output folder +[Ee]xpress/ + +# DocProject is a documentation generator add-in +DocProject/buildhelp/ +DocProject/Help/*.HxT +DocProject/Help/*.HxC +DocProject/Help/*.hhc +DocProject/Help/*.hhk +DocProject/Help/*.hhp +DocProject/Help/Html2 +DocProject/Help/html + +# Click-Once directory +publish/ + +# Publish Web Output +*.[Pp]ublish.xml +*.azurePubxml +# TODO: Comment the next line if you want to checkin your web deploy settings +# but database connection strings (with potential passwords) will be unencrypted +*.pubxml +*.publishproj + +# Microsoft Azure Web App publish settings. Comment the next line if you want to +# checkin your Azure Web App publish settings, but sensitive information contained +# in these scripts will be unencrypted +PublishScripts/ + +# NuGet Packages +*.nupkg +*.snupkg +# The packages folder can be ignored because of Package Restore +**/packages/* +# except build/, which is used as an MSBuild target. +!**/packages/build/ +# Uncomment if necessary however generally it will be regenerated when needed +#!**/packages/repositories.config +# NuGet v3's project.json files produces more ignoreable files +*.nuget.props +*.nuget.targets + +# Microsoft Azure Build Output +csx/ +*.build.csdef + +# Microsoft Azure Emulator +ecf/ +rcf/ + +# Windows Store app package directories and files +AppPackages/ +BundleArtifacts/ +Package.StoreAssociation.xml +_pkginfo.txt + +# Visual Studio cache files +# files ending in .cache can be ignored +*.[Cc]ache +# but keep track of directories ending in .cache +!*.[Cc]ache/ + +# Others +ClientBin/ +~$* +*~ +*.dbmdl +*.dbproj.schemaview +*.pfx +*.publishsettings +node_modules/ +orleans.codegen.cs + +# Since there are multiple workflows, uncomment next line to ignore bower_components +# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) +#bower_components/ + +# RIA/Silverlight projects +Generated_Code/ + +# Backup & report files from converting an old project file +# to a newer Visual Studio version. Backup files are not needed, +# because we have git ;-) +_UpgradeReport_Files/ +Backup*/ +UpgradeLog*.XML +UpgradeLog*.htm + +# SQL Server files +*.mdf +*.ldf + +# Business Intelligence projects +*.rdl.data +*.bim.layout +*.bim_*.settings + +# Microsoft Fakes +FakesAssemblies/ + +# GhostDoc plugin setting file +*.GhostDoc.xml + +# Node.js Tools for Visual Studio +.ntvs_analysis.dat + +# Visual Studio 6 build log +*.plg + +# Visual Studio 6 workspace options file +*.opt + +# Visual Studio LightSwitch build output +**/*.HTMLClient/GeneratedArtifacts +**/*.DesktopClient/GeneratedArtifacts +**/*.DesktopClient/ModelManifest.xml +**/*.Server/GeneratedArtifacts +**/*.Server/ModelManifest.xml +_Pvt_Extensions + +# Paket dependency manager +.paket/paket.exe +paket-files/ + +# FAKE - F# Make +.fake/ + +# JetBrains Rider +.idea/ +*.sln.iml +target/ + +# macOS +.DS_Store diff --git a/Rust/source/Cargo.lock b/Rust/source/Cargo.lock new file mode 100644 index 0000000..6a8c0af --- /dev/null +++ b/Rust/source/Cargo.lock @@ -0,0 +1,98 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "chrono" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" +dependencies = [ + "libc", + "num-integer", + "num-traits", + "time", + "winapi", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.90" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba4aede83fc3617411dc6993bc8c70919750c1c257c6ca6a502aed6e0e2394ae" + +[[package]] +name = "num-integer" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2cc698a63b549a70bc047073d2949cce27cd1c7b0a4a862d08a8031bc2801db" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a64b1ec5cda2586e284722486d802acf1f7dbdc623e2bfc57e65ca1cd099290" +dependencies = [ + "autocfg", +] + +[[package]] +name = "time" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255" +dependencies = [ + "libc", + "wasi", + "winapi", +] + +[[package]] +name = "wasi" +version = "0.10.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "yitidgen" +version = "1.0.0" +dependencies = [ + "chrono", + "lazy_static", +] diff --git a/Rust/source/Cargo.toml b/Rust/source/Cargo.toml new file mode 100644 index 0000000..8664c2f --- /dev/null +++ b/Rust/source/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "yitidgen" +version = "1.0.0" +authors = ["yitter "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +chrono = "0.4.10" +lazy_static = "1.4.0" + +[lib] +name = "yitidgen" +path = "./src/lib.rs" +crate-type = ["cdylib"] diff --git a/Rust/source/src/lib.rs b/Rust/source/src/lib.rs new file mode 100644 index 0000000..080215e --- /dev/null +++ b/Rust/source/src/lib.rs @@ -0,0 +1,21 @@ +mod yitgen; + +use yitgen::gen::YitIdHelper; +use yitgen::contract::*; + +// #[export_name = "SetIdGenerator"] +#[no_mangle] +pub extern "C" fn SetIdGenerator(options: IdGeneratorOptions) { + YitIdHelper::SetIdGenerator(options); +} + +#[no_mangle] +pub extern "C" fn SetWorkerId(workerId: u32) { + YitIdHelper::SetWorkerId(workerId); +} + +#[no_mangle] +pub extern "C" fn NextId() -> i64 { + YitIdHelper::NextId() +} + diff --git a/Rust/source/src/main.rs b/Rust/source/src/main.rs new file mode 100644 index 0000000..88ab0ff --- /dev/null +++ b/Rust/source/src/main.rs @@ -0,0 +1,53 @@ +mod yitgen; + +use yitgen::contract::*; +use yitgen::gen::*; +use std::thread; +use chrono::Utc; +use std::time::Duration; + +fn main() { + println!("Hello, world! Rust"); + + // 总执行次数 + let times = 50000; + + // 是否启用多线程测试 + let multiThread = false; + + // 全局设置一次运行参数 + let mut options = IdGeneratorOptions::New(1); + options.WorkerIdBitLength = 6; + options.SeqBitLength = 6; + //... 可以继续设置其它 options 参数 + YitIdHelper::SetIdGenerator(options); + + // 以下开始测试生成数据,默认5W,单线程,可以修改 multiThread=true 启用多线程。 + loop { + let mut i = 0; + let mut id: i64 = 0; + let start = Utc::now().timestamp_millis(); + + while i < times { + i += 1; + if multiThread { // 这是多线程 + thread::spawn(move || { + id = YitIdHelper::NextId(); + println!("{}, id: {}", i, id); + }); + } else { // 这是单线程 + id = YitIdHelper::NextId(); + } + } + + println!("最后生成的id: {}", id); + if !multiThread { + // 多线程情况下,时间统计不准确 + let end = Utc::now().timestamp_millis(); + println!("单线程用时 {} ms", end - start); + } + + thread::sleep(std::time::Duration::from_millis(2000)); + } +} + diff --git a/Rust/source/src/yitgen/contract/i_snow_worker.rs b/Rust/source/src/yitgen/contract/i_snow_worker.rs new file mode 100644 index 0000000..303d553 --- /dev/null +++ b/Rust/source/src/yitgen/contract/i_snow_worker.rs @@ -0,0 +1,7 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +pub trait ISnowWorker { + fn NextId(&self) -> u64; +} \ No newline at end of file diff --git a/Rust/source/src/yitgen/contract/id_generator_options.rs b/Rust/source/src/yitgen/contract/id_generator_options.rs new file mode 100644 index 0000000..f190505 --- /dev/null +++ b/Rust/source/src/yitgen/contract/id_generator_options.rs @@ -0,0 +1,38 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ + +pub struct IdGeneratorOptions { + /// 雪花计算方法,(1-漂移算法|2-传统算法),默认1 + pub Method: u8, + /// 基础时间(ms单位),不能超过当前系统时间 + pub BaseTime: i64, + /// 机器码,与 WorkerIdBitLength 有关系 + pub WorkerId: u32, + /// 机器码位长,范围:1-21(要求:序列数位长+机器码位长不超过22) + pub WorkerIdBitLength: u8, + /// 序列数位长,范围:2-21(要求:序列数位长+机器码位长不超过22) + pub SeqBitLength: u8, + /// 最大序列数(含),(由 SeqBitLength 计算的最大值) + pub MaxSeqNumber: u32, + /// 最小序列数(含),默认5,不小于5,不大于 MaxSeqNumber + pub MinSeqNumber: u32, + /// 最大漂移次数(含),默认2000,推荐范围 500-20000(与计算能力有关) + pub TopOverCostCount: u32, +} + +impl IdGeneratorOptions { + pub fn New(workerId: u32) -> IdGeneratorOptions { + return IdGeneratorOptions { + Method: 1, + WorkerId: workerId, + BaseTime: 1582136402000, + WorkerIdBitLength: 6, + SeqBitLength: 6, + MaxSeqNumber: 0, + MinSeqNumber: 5, + TopOverCostCount: 2000, + }; + } +} \ No newline at end of file diff --git a/Rust/source/src/yitgen/contract/mod.rs b/Rust/source/src/yitgen/contract/mod.rs new file mode 100644 index 0000000..769f846 --- /dev/null +++ b/Rust/source/src/yitgen/contract/mod.rs @@ -0,0 +1,13 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +mod id_generator_options; +mod i_snow_worker; +mod over_cost_action_arg; + +pub use id_generator_options::IdGeneratorOptions; +pub use i_snow_worker::ISnowWorker; +pub use over_cost_action_arg::OverCostActionArg; + + diff --git a/Rust/source/src/yitgen/contract/over_cost_action_arg.rs b/Rust/source/src/yitgen/contract/over_cost_action_arg.rs new file mode 100644 index 0000000..79f704d --- /dev/null +++ b/Rust/source/src/yitgen/contract/over_cost_action_arg.rs @@ -0,0 +1,12 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +pub struct OverCostActionArg { + ActionType: u32, + TimeTick: u64, + WorkerId: u16, + OverCostCountInOneTerm: u32, + GenCountInOneTerm: u32, + TermIndex: u32, +} \ No newline at end of file diff --git a/Rust/source/src/yitgen/core/mod.rs b/Rust/source/src/yitgen/core/mod.rs new file mode 100644 index 0000000..0dec16d --- /dev/null +++ b/Rust/source/src/yitgen/core/mod.rs @@ -0,0 +1,10 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +mod snow_worker_m1; +mod snow_worker_m2; + +pub use snow_worker_m1::SnowWorkerM1; +pub use snow_worker_m2::SnowWorkerM2; + diff --git a/Rust/source/src/yitgen/core/snow_worker_m1.rs b/Rust/source/src/yitgen/core/snow_worker_m1.rs new file mode 100644 index 0000000..7ed297e --- /dev/null +++ b/Rust/source/src/yitgen/core/snow_worker_m1.rs @@ -0,0 +1,269 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +use super::super::contract::*; +use std::{thread}; +use chrono::Utc; +use std::thread::sleep; +use lazy_static::lazy_static; + +pub struct SnowWorkerM1 { + ///基础时间 + pub BaseTime: i64, + ///机器码 + pub WorkerId: u32, + ///机器码位长 + pub WorkerIdBitLength: u8, + ///自增序列数位长 + pub SeqBitLength: u8, + ///最大序列数(含) + pub MaxSeqNumber: u32, + ///最小序列数(含) + pub MinSeqNumber: u32, + ///最大漂移次数 + pub TopOverCostCount: u32, + + _TimestampShift: u8, + _CurrentSeqNumber: u32, + _LastTimeTick: i64, + _TurnBackTimeTick: i64, + _TurnBackIndex: u8, + _IsOverCost: bool, + _OverCostCountInOneTerm: u32, + _GenCountInOneTerm: u32, + _TermIndex: u32, +} + +impl SnowWorkerM1 { + pub fn Default() -> SnowWorkerM1 { + let options = IdGeneratorOptions::New(1); + return SnowWorkerM1::New(options); + } + + pub fn SetOptions(&mut self, options: IdGeneratorOptions) { + + // BaseTime + if options.BaseTime == 0 { + self.BaseTime = 1582136402000; + } else if options.BaseTime < 631123200000 || options.BaseTime > Utc::now().timestamp_millis() { + panic!("BaseTime error."); + } else { + self.BaseTime = options.BaseTime; + } + + // WorkerIdBitLength + if options.WorkerIdBitLength <= 0 + { + panic!("WorkerIdBitLength error.(range:[1, 21])"); + } + if options.SeqBitLength + options.WorkerIdBitLength > 22 { + panic!("error:WorkerIdBitLength + SeqBitLength <= 22"); + } else { + // self.WorkerIdBitLength = options.WorkerIdBitLength; + self.WorkerIdBitLength = if options.WorkerIdBitLength <= 0 { 6 } else { options.WorkerIdBitLength }; + } + + // WorkerId + let maxWorkerIdNumber = (1 << options.WorkerIdBitLength) - 1; + if options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber { + panic!("WorkerId error. (range:[0, {} ]", if maxWorkerIdNumber <= 0 { 63 } else { maxWorkerIdNumber }); + } else { + self.WorkerId = options.WorkerId; + } + + // SeqBitLength + if options.SeqBitLength < 2 || options.SeqBitLength > 21 { + panic!("SeqBitLength error. (range:[2, 21])"); + } else { + // self.SeqBitLength = options.SeqBitLength; + self.SeqBitLength = if options.SeqBitLength <= 0 { 6 } else { options.SeqBitLength }; + } + + // MaxSeqNumber + let maxSeqNumber = (1 << options.SeqBitLength) - 1; + if options.MaxSeqNumber > maxSeqNumber { + panic!("MaxSeqNumber error. (range:[1, {}]", maxSeqNumber); + } else { + self.MaxSeqNumber = if options.MaxSeqNumber <= 0 { maxSeqNumber } else { options.MaxSeqNumber }; + } + + // MinSeqNumber + if options.MinSeqNumber > maxSeqNumber || options.MinSeqNumber < 5 { + panic!("MinSeqNumber error. (range:[5, {}]", maxSeqNumber); + } else { + self.MinSeqNumber = if options.MinSeqNumber <= 0 { 5 } else { options.MinSeqNumber }; + } + + self.TopOverCostCount = if options.TopOverCostCount == 0 { 2000 } else { options.TopOverCostCount }; + self._TimestampShift = options.WorkerIdBitLength + options.SeqBitLength; + self._CurrentSeqNumber = options.MinSeqNumber; + + if options.Method == 1 { + sleep(std::time::Duration::from_millis(500)); + } + } + + pub fn New(options: IdGeneratorOptions) -> SnowWorkerM1 { + let mut worker = SnowWorkerM1 { + BaseTime: 1582136402000, + WorkerId: 0, + WorkerIdBitLength: 0, + SeqBitLength: 0, + MaxSeqNumber: 0, + MinSeqNumber: 0, + TopOverCostCount: 0, + _TimestampShift: 0, + _CurrentSeqNumber: 0, + _LastTimeTick: 0, + _TurnBackTimeTick: 0, + _TurnBackIndex: 0, + _IsOverCost: false, + _OverCostCountInOneTerm: 0, + _GenCountInOneTerm: 0, + _TermIndex: 0, + }; + + worker.SetOptions(options); + return worker; + } + + pub fn NextId(&mut self) -> i64 { + // println!("SeqBitLength: {}", self.SeqBitLength); + if self._IsOverCost { self.NextOverCostId() } else { self.NextNormalId() } + } + + fn DoGenIdAction(&self, arg: OverCostActionArg) {} + + fn BeginOverCostAction(&self, useTimeTick: i64) {} + + fn EndOverCostAction(&mut self, useTimeTick: i64) { + if self._TermIndex > 10000 { + self._TermIndex = 0; + } + } + + fn BeginTurnBackAction(&self, useTimeTick: i64) {} + + fn EndTurnBackAction(&self, useTimeTick: i64) {} + + fn NextOverCostId(&mut self) -> i64 { + let currentTimeTick = self.GetCurrentTimeTick(); + + if currentTimeTick > self._LastTimeTick { + self.EndOverCostAction(currentTimeTick); + + self._LastTimeTick = currentTimeTick; + self._CurrentSeqNumber = self.MinSeqNumber; + self._IsOverCost = false; + self._OverCostCountInOneTerm = 0; + self._GenCountInOneTerm = 0; + + return self.CalcId(self._LastTimeTick); + } + + if self._OverCostCountInOneTerm >= self.TopOverCostCount { + self.EndOverCostAction(currentTimeTick); + + self._LastTimeTick = self.GetNextTimeTick(); + self._CurrentSeqNumber = self.MinSeqNumber; + self._IsOverCost = false; + self._OverCostCountInOneTerm = 0; + self._GenCountInOneTerm = 0; + + return self.CalcId(self._LastTimeTick); + } + + if self._CurrentSeqNumber > self.MaxSeqNumber { + self._LastTimeTick += 1; + self._CurrentSeqNumber = self.MinSeqNumber; + self._IsOverCost = true; + self._OverCostCountInOneTerm += 1; + self._GenCountInOneTerm += 1; + + return self.CalcId(self._LastTimeTick); + } + + self._GenCountInOneTerm += 1; + return self.CalcId(self._LastTimeTick); + } + + fn NextNormalId(&mut self) -> i64 { + let currentTimeTick = self.GetCurrentTimeTick(); + + if currentTimeTick < self._LastTimeTick { + if self._TurnBackTimeTick < 1 { + self._TurnBackTimeTick = self._LastTimeTick - 1; + self._TurnBackIndex += 1; + + // 每毫秒序列数的前5位是预留位,0用于手工新值,1-4是时间回拨次序 + // 最多4次回拨(防止回拨重叠) + if self._TurnBackIndex > 4 { + self._TurnBackIndex = 1; + } + self.BeginTurnBackAction(self._TurnBackTimeTick); + } + + thread::sleep(std::time::Duration::from_millis(10)); + return self.CalcTurnBackId(self._TurnBackTimeTick); + } + + // 时间追平时,_TurnBackTimeTick清零 + if self._TurnBackTimeTick > 0 { + self.EndTurnBackAction(self._TurnBackTimeTick); + self._TurnBackTimeTick = 0; + } + + if currentTimeTick > self._LastTimeTick { + self._LastTimeTick = currentTimeTick; + self._CurrentSeqNumber = self.MinSeqNumber; + + return self.CalcId(self._LastTimeTick); + } + + if self._CurrentSeqNumber > self.MaxSeqNumber { + self.BeginOverCostAction(currentTimeTick); + + self._TermIndex += 1; + self._LastTimeTick += 1; + self._CurrentSeqNumber = self.MinSeqNumber; + self._IsOverCost = true; + self._OverCostCountInOneTerm = 1; + self._GenCountInOneTerm = 1; + + return self.CalcId(self._LastTimeTick); + } + + return self.CalcId(self._LastTimeTick); + } + + fn CalcId(&mut self, useTimeTick: i64) -> i64 { + let result = (useTimeTick << self._TimestampShift) + + (self.WorkerId << self.SeqBitLength) as i64 + + (self._CurrentSeqNumber) as i64; + self._CurrentSeqNumber += 1; + return result; + } + + fn CalcTurnBackId(&mut self, useTimeTick: i64) -> i64 { + let result = (useTimeTick << self._TimestampShift) + + (self.WorkerId << self.SeqBitLength) as i64 + + (self._TurnBackIndex) as i64; + self._TurnBackTimeTick -= 1; + return result; + } + + fn GetCurrentTimeTick(&self) -> i64 { + return Utc::now().timestamp_millis() - self.BaseTime; + } + + fn GetNextTimeTick(&self) -> i64 { + let mut tempTimeTicker = self.GetCurrentTimeTick(); + + while tempTimeTicker <= self._LastTimeTick { + tempTimeTicker = self.GetCurrentTimeTick(); + } + + return tempTimeTicker; + } +} \ No newline at end of file diff --git a/Rust/source/src/yitgen/core/snow_worker_m2.rs b/Rust/source/src/yitgen/core/snow_worker_m2.rs new file mode 100644 index 0000000..a9093c1 --- /dev/null +++ b/Rust/source/src/yitgen/core/snow_worker_m2.rs @@ -0,0 +1,9 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +use super::super::contract::ISnowWorker; + +pub struct SnowWorkerM2 { + +} \ No newline at end of file diff --git a/Rust/source/src/yitgen/gen/default_id_generator.rs b/Rust/source/src/yitgen/gen/default_id_generator.rs new file mode 100644 index 0000000..c566b5a --- /dev/null +++ b/Rust/source/src/yitgen/gen/default_id_generator.rs @@ -0,0 +1,25 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +use std::{thread, time}; +use std::net::UdpSocket; +use chrono::Utc; +use super::super::contract::*; +use super::super::core::*; +use super::*; +use std::sync::Mutex; +use std::sync::Arc; +use std::borrow::BorrowMut; + +static mut instance2: Option>> = None; + +pub struct DefaultIdGenerator { + pub Worker: SnowWorkerM1, +} + +impl DefaultIdGenerator { + pub fn Default() -> DefaultIdGenerator { + DefaultIdGenerator { Worker: SnowWorkerM1::Default() } + } +} diff --git a/Rust/source/src/yitgen/gen/mod.rs b/Rust/source/src/yitgen/gen/mod.rs new file mode 100644 index 0000000..c0d329c --- /dev/null +++ b/Rust/source/src/yitgen/gen/mod.rs @@ -0,0 +1,9 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +mod default_id_generator; +mod yit_id_helper; + +pub use yit_id_helper::YitIdHelper; +pub use default_id_generator::DefaultIdGenerator; diff --git a/Rust/source/src/yitgen/gen/yit_id_helper.rs b/Rust/source/src/yitgen/gen/yit_id_helper.rs new file mode 100644 index 0000000..ae1e5e7 --- /dev/null +++ b/Rust/source/src/yitgen/gen/yit_id_helper.rs @@ -0,0 +1,42 @@ +/* + * 版权属于:yitter(yitter@126.com) + * 开源地址:https://gitee.com/yitter/idgenerator + */ +use super::super::contract::*; +use super::super::core::*; +use super::*; +use std::sync::Mutex; +use std::sync::Arc; + +pub struct YitIdHelper; + +static mut idGenInstance: Option>> = None; + +impl YitIdHelper { + fn IdGenInstance() -> Arc> { + unsafe { + idGenInstance.get_or_insert_with(|| { + Arc::new(Mutex::new(DefaultIdGenerator::Default())) + }).clone() + } + } + + pub fn SetIdGenerator(options: IdGeneratorOptions) { + let mut idgenArc = YitIdHelper::IdGenInstance(); + let mut idgen = idgenArc.lock().unwrap(); + idgen.Worker.SetOptions(options); + } + + pub fn SetWorkerId(workerId: u32) { + let mut idgenArc = YitIdHelper::IdGenInstance(); + let mut idgen = idgenArc.lock().unwrap(); + let mut options = IdGeneratorOptions::New(workerId); + idgen.Worker.SetOptions(options); + } + + pub fn NextId() -> i64 { + let mut idgenArc = YitIdHelper::IdGenInstance(); + let mut idgen = idgenArc.lock().unwrap(); + idgen.Worker.NextId() + } +} diff --git a/Rust/source/src/yitgen/mod.rs b/Rust/source/src/yitgen/mod.rs new file mode 100644 index 0000000..b12d01c --- /dev/null +++ b/Rust/source/src/yitgen/mod.rs @@ -0,0 +1,3 @@ +pub mod contract; +pub mod core; +pub mod gen; diff --git a/ZeOthers/README.md b/ZeOthers/README.md new file mode 100644 index 0000000..7d3168b --- /dev/null +++ b/ZeOthers/README.md @@ -0,0 +1,7 @@ +# idgenerator + +ṩһЩԵķ汾ѧϰοб£ + +Vlangṩߣ΢ϣ + + diff --git a/ZeOthers/Vlang/README.md b/ZeOthers/Vlang/README.md new file mode 100644 index 0000000..f53407c --- /dev/null +++ b/ZeOthers/Vlang/README.md @@ -0,0 +1,4 @@ +# idgenerator + +ɰṩ Vlang Դ롣Vlang Ŀǰڷչڣڱ롢Чʵȷ滹ռ䡣 + diff --git a/ZeOthers/Vlang/source/contract/IIdGenerator.v b/ZeOthers/Vlang/source/contract/IIdGenerator.v new file mode 100644 index 0000000..c85a917 --- /dev/null +++ b/ZeOthers/Vlang/source/contract/IIdGenerator.v @@ -0,0 +1,5 @@ +module contract + +pub interface IIdGenerator { + new_long() u64 +} \ No newline at end of file diff --git a/ZeOthers/Vlang/source/contract/ISnowWorker.v b/ZeOthers/Vlang/source/contract/ISnowWorker.v new file mode 100644 index 0000000..0494115 --- /dev/null +++ b/ZeOthers/Vlang/source/contract/ISnowWorker.v @@ -0,0 +1,5 @@ +module contract + +pub interface ISnowWorker { + next_id() u64 +} \ No newline at end of file diff --git a/ZeOthers/Vlang/source/contract/IdGeneratorOptions.v b/ZeOthers/Vlang/source/contract/IdGeneratorOptions.v new file mode 100644 index 0000000..f31e5ee --- /dev/null +++ b/ZeOthers/Vlang/source/contract/IdGeneratorOptions.v @@ -0,0 +1,13 @@ +module contract + +pub struct IdGeneratorOptions { +pub mut: + method u16 =1// 雪花计算方法,(1-漂移算法|2-传统算法),默认1 + base_time i64// 基础时间,不能超过当前系统时间 + worker_id u16 =1// 机器码,与 workerid_bitlength 有关系 + workerid_bitlength byte=6// 机器码位长,范围:1-21(要求:序列数位长+机器码位长不超过22) + seq_bitlength byte=6// 序列数位长,范围:2-21(要求:序列数位长+机器码位长不超过22) + max_seqnumber u32// 最大序列数(含),(由seq_bitlength计算的最大值) + min_seqnumber u32// 最小序列数(含),默认5,不小于1,不大于max_seqnumber + top_over_cost_count u32 =2000// 最大漂移次数(含),默认2000,推荐范围500-10000(与计算能力有关) +} \ No newline at end of file diff --git a/ZeOthers/Vlang/source/core/SnowWorkerM1.v b/ZeOthers/Vlang/source/core/SnowWorkerM1.v new file mode 100644 index 0000000..af38d65 --- /dev/null +++ b/ZeOthers/Vlang/source/core/SnowWorkerM1.v @@ -0,0 +1,198 @@ +module core + +import contract +import time +import sync + +pub struct SnowWorkerM1{ +mut: + method u16 // 雪花计算方法,(1-漂移算法|2-传统算法),默认1 + base_time i64 // 基础时间,不能超过当前系统时间 + worker_id u16 // 机器码,与 workerid_bitlength 有关系 + workerid_bitlength byte// 机器码位长,范围:1-21(要求:序列数位长+机器码位长不超过22) + seq_bitlength byte// 序列数位长,范围:2-21(要求:序列数位长+机器码位长不超过22) + max_seqnumber u32 // 最大序列数(含),(由seq_bitlength计算的最大值) + min_seqnumber u32 // 最小序列数(含),默认5,不小于1,不大于max_seqnumber + top_over_cost_count u32 // 最大漂移次数(含),默认2000,推荐范围500-10000(与计算能力有关) + + timestamp_shift byte + current_seqnumber u32 + last_time_tick i64 + turn_back_timetick i64 + turnback_index byte + is_over_cost bool + overcostcount_inoneterm u32 + gencount_inoneterm u32 + term_index u32 + mu sync.Mutex +} + +pub fn make_sf_m1(options &contract.IdGeneratorOptions) &contract.ISnowWorker{ + worker_id := options.worker_id + + mut workerid_bitlength:=byte(6) + if options.workerid_bitlength != 0 { + workerid_bitlength = options.workerid_bitlength + } + mut seq_bitlength:=byte(6) + if options.seq_bitlength != 0 { + seq_bitlength = options.seq_bitlength + } + mut max_seqnumber:=u32(0) + if options.max_seqnumber > 0 { + max_seqnumber = options.max_seqnumber + } else { + max_seqnumber = (1< 10000 { + m1.term_index = 0 + } +} + +// fn (m1 &SnowWorkerM1) begin_turn_back_action(use_time_tick i64) { + +// } + +// fn (m1 &SnowWorkerM1) end_turn_back_action(use_time_tick i64) { + +// } + +fn (mut m1 SnowWorkerM1) next_over_cost_id() u64 { + current_time_tick := m1.get_current_time_tick() + if current_time_tick > m1.last_time_tick { + m1.end_over_cost_action() + m1.last_time_tick = current_time_tick + m1.current_seqnumber = m1.min_seqnumber + m1.is_over_cost = false + m1.overcostcount_inoneterm = 0 + m1.gencount_inoneterm = 0 + return m1.calc_id() + } + if m1.overcostcount_inoneterm >= m1.top_over_cost_count { + m1.end_over_cost_action() + m1.last_time_tick = m1.get_next_time_tick() + m1.current_seqnumber = m1.min_seqnumber + m1.is_over_cost = false + m1.overcostcount_inoneterm = 0 + m1.gencount_inoneterm = 0 + return m1.calc_id() + } + if m1.current_seqnumber > m1.max_seqnumber { + m1.last_time_tick++ + m1.current_seqnumber = m1.min_seqnumber + m1.is_over_cost = true + m1.overcostcount_inoneterm++ + m1.gencount_inoneterm++ + + return m1.calc_id() + } + m1.gencount_inoneterm++ + return m1.calc_id() +} + +fn (mut m1 SnowWorkerM1) next_normal_id() u64 { + current_time_tick := m1.get_current_time_tick() + if current_time_tick < m1.last_time_tick { + if m1.turn_back_timetick < 1 { + m1.turn_back_timetick = m1.last_time_tick - 1 + m1.turnback_index++ + // 每毫秒序列数的前5位是预留位,0用于手工新值,1-4是时间回拨次序 + // 最多4次回拨(防止回拨重叠) + if m1.turnback_index > 4 { + m1.turnback_index = 1 + } + // m1.begin_turn_back_action(m1.turn_back_timetick) + } + return m1.calc_turn_back_id() + } + // 时间追平时,turn_back_timetick清零 + if m1.turn_back_timetick > 0 { + // m1.end_turn_back_action(m1.turn_back_timetick) + m1.turn_back_timetick = 0 + } + if current_time_tick > m1.last_time_tick { + m1.last_time_tick = current_time_tick + m1.current_seqnumber = m1.min_seqnumber + return m1.calc_id() + } + if m1.current_seqnumber > m1.max_seqnumber { + // m1.begin_over_cost_action(current_time_tick) + m1.term_index++ + m1.last_time_tick++ + m1.current_seqnumber = m1.min_seqnumber + m1.is_over_cost = true + m1.overcostcount_inoneterm = 1 + m1.gencount_inoneterm = 1 + + return m1.calc_id() + } + return m1.calc_id() +} + +fn (mut m1 SnowWorkerM1) calc_id() u64 { + result := u64(m1.last_time_tick< time.now().unix_time_milli() { + panic("base_time error.") + } + + if options.seq_bitlength+options.workerid_bitlength > 22 { + panic("error:workerid_bitlength + seq_bitlength <= 22") + } + + max_workerid_number := 1< max_workerid_number { + panic("WorkerId error. (range:[1, " + max_workerid_number.str() + "]") + } + + if options.seq_bitlength < 2 || options.seq_bitlength > 21 { + panic("seq_bitlength error. (range:[2, 21])") + } + + max_seqnumber := 1< max_seqnumber { + panic("MaxSeqNumber error. (range:[1, " + max_seqnumber.str() + "]") + } + + if options.min_seqnumber > max_seqnumber { + panic("MinSeqNumber error. (range:[1, " + max_seqnumber.str() + "]") + } + + match options.method { + 1 { + return &DefaultIdGenerator{ + options: options, + snow_worker: core.make_sf_m1(options), + } + } + 2 { + return &DefaultIdGenerator{ + options: options, + snow_worker: core.make_sf_m2(options), + } + } + else { + return &DefaultIdGenerator{ + options: options, + snow_worker: core.make_sf_m1(options), + } + } + } + + +} + +pub fn (mut dig DefaultIdGenerator) new_long() u64 { + return dig.snow_worker.next_id() +} \ No newline at end of file diff --git a/ZeOthers/Vlang/source/gen/YitIdHelper.v b/ZeOthers/Vlang/source/gen/YitIdHelper.v new file mode 100644 index 0000000..9bbcc69 --- /dev/null +++ b/ZeOthers/Vlang/source/gen/YitIdHelper.v @@ -0,0 +1,12 @@ +module gen + +import contract + +pub struct YitIdHelper { +mut: + id_gen contract.IIdGenerator +} + +pub fn (yih &YitIdHelper) next_id() u64 { + return yih.id_gen.new_long() +} \ No newline at end of file diff --git a/ZeOthers/Vlang/source/test b/ZeOthers/Vlang/source/test new file mode 100644 index 0000000000000000000000000000000000000000..24b2f2c0198605a8bf90c022fd08c16be578d92b GIT binary patch literal 68456 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 z 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 CBntv&C$&EQS^{Gcz+-%*@OdGmQ-YxpVG45fd{n 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 literal 0 HcmV?d00001 diff --git "a/tester/\346\257\217\346\254\2415W\345\271\266\345\217\221(\345\276\252\347\216\257).png" "b/tester/\346\257\217\346\254\2415W\345\271\266\345\217\221(\345\276\252\347\216\257).png" new file mode 100644 index 0000000000000000000000000000000000000000..7f9df0ac83fc1ddf7c7c79db8a52b74e4d7b4940 GIT binary patch literal 102371 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 Hd>Hm$*%b*- literal 0 HcmV?d00001 -- GitLab