提交 cbb5893e 编写于 作者: Z zhouzj

init

上级 265d503e
## 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
# 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/)
# idgenerator
#### 介绍
用一种全新的雪花漂移算法,让ID更短、生成速度更快。特点:
1.ID更短,是传统算法的几倍,用50年都不会超过js(Number)的最大值。
2.生成速度更快,0.1秒可生成50万个。(i7笔记本)
3.支持时间回拨处理。
4.支持手工插入新ID。
5.在算法漂移时,可抛出事件。
6.目前是C#版,很快会出java、php等版本。
支持QQ群:646049993
#### 软件架构
软件架构说明
@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
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);
}
}
}
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}");
}
}
}
}
<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>

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
using System;
namespace Yitter.IdGenerator
{
public interface IIdGenerator
{
Action<OverCostActionArg> GenIdActionAsync { get; set; }
long NewLong();
}
}
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();
}
}
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()
{
}
}
}
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;
}
}
}
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();
}
}
}
}
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;
}
}
}
}
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();
}
}
}
<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>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册