init
This commit is contained in:
258
.gitignore
vendored
Normal file
258
.gitignore
vendored
Normal file
@@ -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
|
||||||
37
README.en.md
Normal file
37
README.en.md
Normal file
@@ -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/)
|
||||||
17
README.md
Normal file
17
README.md
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
# idgenerator
|
||||||
|
|
||||||
|
#### 介绍
|
||||||
|
用一种全新的雪花漂移算法,让ID更短、生成速度更快。特点:
|
||||||
|
1.ID更短,是传统算法的几倍,用50年都不会超过js(Number)的最大值。
|
||||||
|
2.生成速度更快,0.1秒可生成50万个。(i7笔记本)
|
||||||
|
3.支持时间回拨处理。
|
||||||
|
4.支持手工插入新ID。
|
||||||
|
5.在算法漂移时,可抛出事件。
|
||||||
|
6.目前是C#版,很快会出java、php等版本。
|
||||||
|
|
||||||
|
支持QQ群:646049993
|
||||||
|
|
||||||
|
|
||||||
|
#### 软件架构
|
||||||
|
软件架构说明
|
||||||
|
|
||||||
37
auto_commit.bat
Normal file
37
auto_commit.bat
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
@echo off
|
||||||
|
|
||||||
|
set result=[OK]
|
||||||
|
set tag=[OK]
|
||||||
|
set msg="auto commit"
|
||||||
|
|
||||||
|
echo --------------------------------------------------------
|
||||||
|
|
||||||
|
if not "%1" == "" (
|
||||||
|
SET msg=%1
|
||||||
|
)
|
||||||
|
|
||||||
|
git add -A
|
||||||
|
git commit -am %msg%
|
||||||
|
|
||||||
|
|
||||||
|
git push
|
||||||
|
if "%errorlevel%"=="1" goto ERR
|
||||||
|
|
||||||
|
goto END
|
||||||
|
|
||||||
|
:ERR
|
||||||
|
set result=[error]
|
||||||
|
set tag=[error]
|
||||||
|
|
||||||
|
:END
|
||||||
|
|
||||||
|
|
||||||
|
echo %tag% result: %result%
|
||||||
|
echo ========================================================
|
||||||
|
|
||||||
|
if "%tag%"=="×" (
|
||||||
|
SET __ERROR__=true
|
||||||
|
@pause
|
||||||
|
)
|
||||||
|
|
||||||
|
:QUIT
|
||||||
49
src/Yitter.IdGenTest/GenTest.cs
Normal file
49
src/Yitter.IdGenTest/GenTest.cs
Normal file
@@ -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<long> idList = new List<long>();
|
||||||
|
private int GenNumber;
|
||||||
|
private int WorkerId;
|
||||||
|
|
||||||
|
|
||||||
|
public GenTest(IIdGenerator idGen, int genNumber, int workerId)
|
||||||
|
{
|
||||||
|
GenNumber = genNumber;
|
||||||
|
IdGen = idGen;
|
||||||
|
WorkerId = workerId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void GenId()
|
||||||
|
{
|
||||||
|
Thread t = new Thread(new ThreadStart(Gen1Start));
|
||||||
|
t.Start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Gen1Start()
|
||||||
|
{
|
||||||
|
DateTime start = DateTime.Now;
|
||||||
|
|
||||||
|
for (int i = 0; i < GenNumber; i++)
|
||||||
|
{
|
||||||
|
var id = IdGen.NewLong();
|
||||||
|
//ids.Add(id, i);
|
||||||
|
idList.Add(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
DateTime end = DateTime.Now;
|
||||||
|
Console.WriteLine($"++++++++++++++++++++++++++++++++++++++++WorkerId: {WorkerId}, total: {(end - start).TotalSeconds} s");
|
||||||
|
Interlocked.Increment(ref Program.Count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
156
src/Yitter.IdGenTest/Program.cs
Normal file
156
src/Yitter.IdGenTest/Program.cs
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using Yitter.IdGenerator;
|
||||||
|
|
||||||
|
namespace Yitter.OrgSystem.TestA
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
static int workerCount = 1;
|
||||||
|
static int genIdCount = 50000; // 计算ID数量
|
||||||
|
static bool single = true;
|
||||||
|
static bool outputLog = true;
|
||||||
|
static IIdGenerator IdGen = null;
|
||||||
|
static IList<GenTest> testList = new List<GenTest>();
|
||||||
|
static bool checkResult = false;
|
||||||
|
public static int Count = 0;
|
||||||
|
|
||||||
|
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
Go();
|
||||||
|
Thread.Sleep(500);
|
||||||
|
Console.WriteLine("Hello World!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Go()
|
||||||
|
{
|
||||||
|
Count = 0;
|
||||||
|
testList = new List<GenTest>();
|
||||||
|
|
||||||
|
var newConfig = new IdGeneratorOptions()
|
||||||
|
{
|
||||||
|
Method = 1,
|
||||||
|
StartTime = DateTime.Now.AddYears(-1),
|
||||||
|
|
||||||
|
//TopOverCostCount = 1000,
|
||||||
|
WorkerIdBitLength = 6,
|
||||||
|
SeqBitLength = 6,
|
||||||
|
|
||||||
|
//MinSeqNumber = 11,
|
||||||
|
//MaxSeqNumber = 200,
|
||||||
|
};
|
||||||
|
|
||||||
|
// ++++++++++++++++++++++++++++++++
|
||||||
|
if (single)
|
||||||
|
{
|
||||||
|
newConfig.WorkerId = 1;
|
||||||
|
IdGeneratorOptions options1 = (newConfig);
|
||||||
|
if (IdGen == null)
|
||||||
|
{
|
||||||
|
IdGen = new YitIdGenerator(options1);
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for (int i = 1; i < workerCount + 1; i++)
|
||||||
|
{
|
||||||
|
IdGeneratorOptions options =
|
||||||
|
new IdGeneratorOptions()
|
||||||
|
{
|
||||||
|
WorkerId = (ushort)i, // workerId 不能设置为0
|
||||||
|
WorkerIdBitLength = newConfig.WorkerIdBitLength,
|
||||||
|
SeqBitLength = newConfig.SeqBitLength,
|
||||||
|
MinSeqNumber = newConfig.MinSeqNumber,
|
||||||
|
MaxSeqNumber = newConfig.MaxSeqNumber,
|
||||||
|
Method = newConfig.Method,
|
||||||
|
};
|
||||||
|
|
||||||
|
Console.WriteLine("Gen:" + i);
|
||||||
|
var idGen2 = new YitIdGenerator(options);
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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}");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
16
src/Yitter.IdGenTest/Yitter.IdGenTest.csproj
Normal file
16
src/Yitter.IdGenTest/Yitter.IdGenTest.csproj
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net5.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\Yitter.IdGenerator\Yitter.IdGenerator.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
31
src/Yitter.IdGenerator.sln
Normal file
31
src/Yitter.IdGenerator.sln
Normal file
@@ -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
|
||||||
11
src/Yitter.IdGenerator/IIdGenerator.cs
Normal file
11
src/Yitter.IdGenerator/IIdGenerator.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Yitter.IdGenerator
|
||||||
|
{
|
||||||
|
public interface IIdGenerator
|
||||||
|
{
|
||||||
|
Action<OverCostActionArg> GenIdActionAsync { get; set; }
|
||||||
|
|
||||||
|
long NewLong();
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/Yitter.IdGenerator/ISnowWorker.cs
Normal file
14
src/Yitter.IdGenerator/ISnowWorker.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using static Yitter.IdGenerator.IIdGenerator;
|
||||||
|
|
||||||
|
namespace Yitter.IdGenerator
|
||||||
|
{
|
||||||
|
internal interface ISnowWorker
|
||||||
|
{
|
||||||
|
Action<OverCostActionArg> GenAction { get; set; }
|
||||||
|
|
||||||
|
long NextId();
|
||||||
|
}
|
||||||
|
}
|
||||||
65
src/Yitter.IdGenerator/IdGeneratorOptions.cs
Normal file
65
src/Yitter.IdGenerator/IdGeneratorOptions.cs
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Yitter.IdGenerator
|
||||||
|
{
|
||||||
|
public class IdGeneratorOptions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 雪花计算方法
|
||||||
|
/// (1|2)
|
||||||
|
/// </summary>
|
||||||
|
public short Method { get; set; } = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 开始时间(UTC格式)
|
||||||
|
/// 不能超过当前系统时间
|
||||||
|
/// </summary>
|
||||||
|
public DateTime StartTime { get; set; } = DateTime.MinValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 机器码
|
||||||
|
/// 与 WorkerIdBitLength 有关系
|
||||||
|
/// </summary>
|
||||||
|
public ushort WorkerId { get; set; } = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 机器码位长
|
||||||
|
/// 范围:2-21(要求:序列数位长+机器码位长不超过22)。
|
||||||
|
/// 建议范围:6-12。
|
||||||
|
/// </summary>
|
||||||
|
public byte WorkerIdBitLength { get; set; } = 6;//10;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 序列数位长
|
||||||
|
/// 范围:2-21(要求:序列数位长+机器码位长不超过22)。
|
||||||
|
/// 建议范围:6-14。
|
||||||
|
/// </summary>
|
||||||
|
public byte SeqBitLength { get; set; } = 6;//10;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最大序列数(含)
|
||||||
|
/// (由SeqBitLength计算的最大值)
|
||||||
|
/// </summary>
|
||||||
|
public int MaxSeqNumber { get; set; } = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最小序列数(含)
|
||||||
|
/// 默认11,不小于5,不大于MaxSeqNumber-2
|
||||||
|
/// </summary>
|
||||||
|
public ushort MinSeqNumber { get; set; } = 11;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最大漂移次数(含),
|
||||||
|
/// 默认2000,推荐范围500-10000(与计算能力有关)
|
||||||
|
/// </summary>
|
||||||
|
public int TopOverCostCount { get; set; } = 2000;
|
||||||
|
|
||||||
|
|
||||||
|
public IdGeneratorOptions()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
26
src/Yitter.IdGenerator/OverCostActionArg.cs
Normal file
26
src/Yitter.IdGenerator/OverCostActionArg.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Yitter.IdGenerator
|
||||||
|
{
|
||||||
|
public class OverCostActionArg
|
||||||
|
{
|
||||||
|
public int ActionType { get; set; }
|
||||||
|
public long TimeTick { get; set; }
|
||||||
|
public ushort WorkerId { get; set; }
|
||||||
|
public int OverCostCountInOneTerm { get; set; }
|
||||||
|
public int GenCountInOneTerm { get; set; }
|
||||||
|
public 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
297
src/Yitter.IdGenerator/SnowWorkerM1.cs
Normal file
297
src/Yitter.IdGenerator/SnowWorkerM1.cs
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
using System;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Yitter.IdGenerator
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 雪花漂移算法
|
||||||
|
/// </summary>
|
||||||
|
internal class SnowWorkerM1 : ISnowWorker
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 基础时间
|
||||||
|
/// </summary>
|
||||||
|
protected readonly DateTime StartTimeUtc = new DateTime(2020, 2, 20, 2, 20, 2, 20, DateTimeKind.Utc);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 机器码
|
||||||
|
/// </summary>
|
||||||
|
protected readonly ushort WorkerId = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 机器码位长
|
||||||
|
/// (机器码+序列数<=22位)
|
||||||
|
/// </summary>
|
||||||
|
protected readonly byte WorkerIdBitLength = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 自增序列数位长
|
||||||
|
/// (机器码+序列数<=22位)
|
||||||
|
/// </summary>
|
||||||
|
protected readonly byte SeqBitLength = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最大序列数(含此值)
|
||||||
|
/// 超过最大值,就会从MinSeqNumber开始
|
||||||
|
/// </summary>
|
||||||
|
protected readonly int MaxSeqNumber = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最小序列数(含此值)
|
||||||
|
/// </summary>
|
||||||
|
protected readonly ushort MinSeqNumber = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最大漂移次数
|
||||||
|
/// </summary>
|
||||||
|
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 bool _IsOverCost = false;
|
||||||
|
protected int _OverCostCountInOneTerm = 0;
|
||||||
|
protected int _GenCountInOneTerm = 0;
|
||||||
|
protected int _TermIndex = 0;
|
||||||
|
public Action<OverCostActionArg> GenAction { get; set; }
|
||||||
|
|
||||||
|
public SnowWorkerM1(IdGeneratorOptions options)
|
||||||
|
{
|
||||||
|
WorkerId = options.WorkerId;
|
||||||
|
WorkerIdBitLength = options.WorkerIdBitLength;
|
||||||
|
SeqBitLength = options.SeqBitLength;
|
||||||
|
MaxSeqNumber = options.MaxSeqNumber;
|
||||||
|
MinSeqNumber = options.MinSeqNumber;
|
||||||
|
_CurrentSeqNumber = options.MinSeqNumber;
|
||||||
|
TopOverCostCount = options.TopOverCostCount;
|
||||||
|
|
||||||
|
if (options.StartTime != DateTime.MinValue)
|
||||||
|
{
|
||||||
|
StartTimeUtc = options.StartTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 如果没有初始化,则随机一个数值
|
||||||
|
if (WorkerId < 1)
|
||||||
|
{
|
||||||
|
WorkerId = (ushort)DateTime.Now.Millisecond;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SeqBitLength == 0)
|
||||||
|
{
|
||||||
|
SeqBitLength = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (WorkerIdBitLength == 0)
|
||||||
|
{
|
||||||
|
WorkerIdBitLength = 10;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (MaxSeqNumber == 0)
|
||||||
|
{
|
||||||
|
MaxSeqNumber = (int)Math.Pow(2, SeqBitLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
_TimestampShift = (byte)(WorkerIdBitLength + SeqBitLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void DoGenIdAction(OverCostActionArg arg)
|
||||||
|
{
|
||||||
|
Task.Run(() =>
|
||||||
|
{
|
||||||
|
if (arg.ActionType == 2 && _TermIndex > 10000)
|
||||||
|
{
|
||||||
|
_TermIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
GenAction(arg);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private void BeginOverCostCallBack(in long useTimeTick)
|
||||||
|
{
|
||||||
|
if (GenAction == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoGenIdAction(new OverCostActionArg(
|
||||||
|
WorkerId,
|
||||||
|
useTimeTick,
|
||||||
|
1,
|
||||||
|
_OverCostCountInOneTerm,
|
||||||
|
_GenCountInOneTerm,
|
||||||
|
_TermIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EndOverCostCallBack(in long useTimeTick)
|
||||||
|
{
|
||||||
|
if (GenAction == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoGenIdAction(new OverCostActionArg(
|
||||||
|
WorkerId,
|
||||||
|
useTimeTick,
|
||||||
|
2,
|
||||||
|
_OverCostCountInOneTerm,
|
||||||
|
_GenCountInOneTerm,
|
||||||
|
_TermIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TurnBackCallBack(in long useTimeTick)
|
||||||
|
{
|
||||||
|
if (GenAction == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoGenIdAction(new OverCostActionArg(
|
||||||
|
WorkerId,
|
||||||
|
useTimeTick,
|
||||||
|
8,
|
||||||
|
_OverCostCountInOneTerm,
|
||||||
|
_GenCountInOneTerm,
|
||||||
|
_TermIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
private long NextOverCostId()
|
||||||
|
{
|
||||||
|
long currentTimeTick = GetCurrentTimeTick();
|
||||||
|
|
||||||
|
if (currentTimeTick > _LastTimeTick)
|
||||||
|
{
|
||||||
|
EndOverCostCallBack(currentTimeTick);
|
||||||
|
|
||||||
|
_LastTimeTick = currentTimeTick;
|
||||||
|
_CurrentSeqNumber = MinSeqNumber;
|
||||||
|
_IsOverCost = false;
|
||||||
|
_OverCostCountInOneTerm = 0;
|
||||||
|
_GenCountInOneTerm = 0;
|
||||||
|
|
||||||
|
return CalcId(_LastTimeTick);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_OverCostCountInOneTerm >= TopOverCostCount)
|
||||||
|
{
|
||||||
|
EndOverCostCallBack(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)
|
||||||
|
{
|
||||||
|
_LastTimeTick = currentTimeTick;
|
||||||
|
_CurrentSeqNumber = MinSeqNumber;
|
||||||
|
|
||||||
|
return CalcId(_LastTimeTick);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_CurrentSeqNumber > MaxSeqNumber)
|
||||||
|
{
|
||||||
|
BeginOverCostCallBack(currentTimeTick);
|
||||||
|
|
||||||
|
_TermIndex++;
|
||||||
|
_LastTimeTick++;
|
||||||
|
_CurrentSeqNumber = MinSeqNumber;
|
||||||
|
_IsOverCost = true;
|
||||||
|
_OverCostCountInOneTerm++;
|
||||||
|
_GenCountInOneTerm = 0;
|
||||||
|
|
||||||
|
return CalcId(_LastTimeTick);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (currentTimeTick < _LastTimeTick)
|
||||||
|
{
|
||||||
|
if (_TurnBackTimeTick < 1)
|
||||||
|
{
|
||||||
|
_TurnBackTimeTick = _LastTimeTick - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Thread.Sleep(10);
|
||||||
|
TurnBackCallBack(_TurnBackTimeTick);
|
||||||
|
|
||||||
|
return CalcTurnBackId(_TurnBackTimeTick);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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) + 0);
|
||||||
|
|
||||||
|
_TurnBackTimeTick--;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual long GetCurrentTimeTick()
|
||||||
|
{
|
||||||
|
return (long)(DateTime.UtcNow - StartTimeUtc).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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
49
src/Yitter.IdGenerator/SnowWorkerM2.cs
Normal file
49
src/Yitter.IdGenerator/SnowWorkerM2.cs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Yitter.IdGenerator
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 常规雪花算法
|
||||||
|
/// </summary>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
84
src/Yitter.IdGenerator/YitIdGenerator.cs
Normal file
84
src/Yitter.IdGenerator/YitIdGenerator.cs
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
|
|
||||||
|
namespace Yitter.IdGenerator
|
||||||
|
{
|
||||||
|
public class YitIdGenerator : IIdGenerator
|
||||||
|
{
|
||||||
|
private ISnowWorker _SnowWorker { get; set; }
|
||||||
|
|
||||||
|
public Action<OverCostActionArg> GenIdActionAsync
|
||||||
|
{
|
||||||
|
get => _SnowWorker.GenAction;
|
||||||
|
set => _SnowWorker.GenAction = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public YitIdGenerator(IdGeneratorOptions options)
|
||||||
|
{
|
||||||
|
if (options == null)
|
||||||
|
{
|
||||||
|
throw new ApplicationException("options error.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.StartTime > DateTime.Now)
|
||||||
|
{
|
||||||
|
throw new ApplicationException("StartTime error.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.SeqBitLength + options.WorkerIdBitLength > 22)
|
||||||
|
{
|
||||||
|
throw new ApplicationException("不满足条件:WorkerIdBitLength + SeqBitLength <= 22");
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxWorkerIdNumber = Math.Pow(2, options.WorkerIdBitLength) - 1;
|
||||||
|
if (options.WorkerId < 1 || options.WorkerId > maxWorkerIdNumber)
|
||||||
|
{
|
||||||
|
throw new ApplicationException("WorkerId is error. (range:[1, " + maxWorkerIdNumber + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options.SeqBitLength < 2 || options.SeqBitLength > 21)
|
||||||
|
{
|
||||||
|
throw new ApplicationException("SeqBitLength is error. (range:[2, 21])");
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxSeqNumber = Math.Pow(2, options.SeqBitLength) - 1;
|
||||||
|
if (options.MaxSeqNumber < 0 || options.MaxSeqNumber > maxSeqNumber)
|
||||||
|
{
|
||||||
|
throw new ApplicationException("MaxSeqNumber is error. (range:[1, " + maxSeqNumber + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
var maxValue = maxSeqNumber - 2;
|
||||||
|
if (options.MinSeqNumber < 5 || options.MinSeqNumber > maxValue)
|
||||||
|
{
|
||||||
|
throw new ApplicationException("MinSeqNumber is error. (range:[5, " + 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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
18
src/Yitter.IdGenerator/Yitter.IdGenerator.csproj
Normal file
18
src/Yitter.IdGenerator/Yitter.IdGenerator.csproj
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<LangVersion>latest</LangVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||||
|
<WarningLevel>5</WarningLevel>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
Reference in New Issue
Block a user