mirror of
https://gitee.com/dotnetchina/OpenAuth.Net.git
synced 2025-07-15 23:13:40 +08:00
调整雪花算法
This commit is contained in:
parent
31811e9d9c
commit
a333234f0c
29
Infrastructure/Snowflake/Contract/IIdGenerator.cs
Normal file
29
Infrastructure/Snowflake/Contract/IIdGenerator.cs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* 版权属于:yitter(yitter@126.com)
|
||||||
|
* 开源地址:https://gitee.com/yitter/idgenerator
|
||||||
|
* 版权协议:MIT
|
||||||
|
* 版权说明:只要保留本版权,你可以免费使用、修改、分发本代码。
|
||||||
|
* 免责条款:任何因为本代码产生的系统、法律、政治、宗教问题,均与版权所有者无关。
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Yitter.IdGenerator
|
||||||
|
{
|
||||||
|
public interface IIdGenerator
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 生成过程中产生的事件
|
||||||
|
/// </summary>
|
||||||
|
Action<OverCostActionArg> GenIdActionAsync { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成新的long型Id
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
long NewLong();
|
||||||
|
|
||||||
|
// Guid NewGuid();
|
||||||
|
}
|
||||||
|
}
|
22
Infrastructure/Snowflake/Contract/ISnowWorker.cs
Normal file
22
Infrastructure/Snowflake/Contract/ISnowWorker.cs
Normal file
@ -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<OverCostActionArg> GenAction { get; set; }
|
||||||
|
|
||||||
|
long NextId();
|
||||||
|
}
|
||||||
|
}
|
80
Infrastructure/Snowflake/Contract/IdGeneratorOptions.cs
Normal file
80
Infrastructure/Snowflake/Contract/IdGeneratorOptions.cs
Normal file
@ -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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 雪花计算方法
|
||||||
|
/// (1-漂移算法|2-传统算法),默认1
|
||||||
|
/// </summary>
|
||||||
|
public virtual short Method { get; set; } = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 基础时间(UTC格式)
|
||||||
|
/// 不能超过当前系统时间
|
||||||
|
/// </summary>
|
||||||
|
public virtual DateTime BaseTime { get; set; } = new DateTime(2020, 2, 20, 2, 20, 2, 20, DateTimeKind.Utc);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 机器码
|
||||||
|
/// 与 WorkerIdBitLength 有关系
|
||||||
|
/// (ushort类型,最大值65535,如果有更高要求,请修改数据类型,或联系作者)
|
||||||
|
/// </summary>
|
||||||
|
public virtual ushort WorkerId { get; set; } = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 机器码位长
|
||||||
|
/// 范围:1-21(要求:序列数位长+机器码位长不超过22)。
|
||||||
|
/// 建议范围:6-12。
|
||||||
|
/// </summary>
|
||||||
|
public virtual byte WorkerIdBitLength { get; set; } = 6;//10;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 序列数位长
|
||||||
|
/// 范围:2-21(要求:序列数位长+机器码位长不超过22)。
|
||||||
|
/// 建议范围:6-14。
|
||||||
|
/// </summary>
|
||||||
|
public virtual byte SeqBitLength { get; set; } = 6;//10;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最大序列数(含)
|
||||||
|
/// (由SeqBitLength计算的最大值)
|
||||||
|
/// </summary>
|
||||||
|
public virtual int MaxSeqNumber { get; set; } = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最小序列数(含)
|
||||||
|
/// 默认5,不小于1,不大于MaxSeqNumber
|
||||||
|
/// </summary>
|
||||||
|
public virtual ushort MinSeqNumber { get; set; } = 5;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 最大漂移次数(含),
|
||||||
|
/// 默认2000,推荐范围500-10000(与计算能力有关)
|
||||||
|
/// </summary>
|
||||||
|
public virtual int TopOverCostCount { get; set; } = 2000;
|
||||||
|
|
||||||
|
|
||||||
|
public IdGeneratorOptions()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public IdGeneratorOptions(ushort workerId)
|
||||||
|
{
|
||||||
|
WorkerId = workerId;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
57
Infrastructure/Snowflake/Contract/OverCostActionArg.cs
Normal file
57
Infrastructure/Snowflake/Contract/OverCostActionArg.cs
Normal file
@ -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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Id生成时回调参数
|
||||||
|
/// </summary>
|
||||||
|
public class OverCostActionArg
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 事件类型
|
||||||
|
/// 1-开始,2-结束,8-漂移
|
||||||
|
/// </summary>
|
||||||
|
public virtual int ActionType { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 时间戳
|
||||||
|
/// </summary>
|
||||||
|
public virtual long TimeTick { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 机器码
|
||||||
|
/// </summary>
|
||||||
|
public virtual ushort WorkerId { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 漂移计算次数
|
||||||
|
/// </summary>
|
||||||
|
public virtual int OverCostCountInOneTerm { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 漂移期间生产ID个数
|
||||||
|
/// </summary>
|
||||||
|
public virtual int GenCountInOneTerm { get; set; }
|
||||||
|
/// <summary>
|
||||||
|
/// 漂移周期
|
||||||
|
/// </summary>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,13 @@
|
|||||||
using System;
|
/*
|
||||||
|
* 版权属于:yitter(yitter@126.com)
|
||||||
|
* 开源地址:https://gitee.com/yitter/idgenerator
|
||||||
|
* 版权协议:MIT
|
||||||
|
* 版权说明:只要保留本版权,你可以免费使用、修改、分发本代码。
|
||||||
|
* 免责条款:任何因为本代码产生的系统、法律、政治、宗教问题,均与版权所有者无关。
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
@ -12,7 +21,7 @@ namespace Yitter.IdGenerator
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// 基础时间
|
/// 基础时间
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected readonly DateTime StartTimeUtc = new DateTime(2020, 2, 20, 2, 20, 2, 20, DateTimeKind.Utc);
|
protected readonly DateTime BaseTime;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 机器码
|
/// 机器码
|
||||||
@ -21,24 +30,21 @@ namespace Yitter.IdGenerator
|
|||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 机器码位长
|
/// 机器码位长
|
||||||
/// (机器码+序列数<=22位)
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected readonly byte WorkerIdBitLength = 0;
|
protected readonly byte WorkerIdBitLength = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 自增序列数位长
|
/// 自增序列数位长
|
||||||
/// (机器码+序列数<=22位)
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected readonly byte SeqBitLength = 0;
|
protected readonly byte SeqBitLength = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 最大序列数(含此值)
|
/// 最大序列数(含)
|
||||||
/// 超过最大值,就会从MinSeqNumber开始
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected readonly int MaxSeqNumber = 0;
|
protected readonly int MaxSeqNumber = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 最小序列数(含此值)
|
/// 最小序列数(含)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected readonly ushort MinSeqNumber = 0;
|
protected readonly ushort MinSeqNumber = 0;
|
||||||
|
|
||||||
@ -53,13 +59,19 @@ namespace Yitter.IdGenerator
|
|||||||
protected ushort _CurrentSeqNumber;
|
protected ushort _CurrentSeqNumber;
|
||||||
protected long _LastTimeTick = -1L;
|
protected long _LastTimeTick = -1L;
|
||||||
protected long _TurnBackTimeTick = -1L;
|
protected long _TurnBackTimeTick = -1L;
|
||||||
|
protected byte _TurnBackIndex = 0;
|
||||||
|
|
||||||
protected bool _IsOverCost = false;
|
protected bool _IsOverCost = false;
|
||||||
protected int _OverCostCountInOneTerm = 0;
|
protected int _OverCostCountInOneTerm = 0;
|
||||||
protected int _GenCountInOneTerm = 0;
|
protected int _GenCountInOneTerm = 0;
|
||||||
protected int _TermIndex = 0;
|
protected int _TermIndex = 0;
|
||||||
|
|
||||||
|
//private static long _StartTimeTick = 0;
|
||||||
|
//private static long _BaseTimeTick = 0;
|
||||||
|
|
||||||
public Action<OverCostActionArg> GenAction { get; set; }
|
public Action<OverCostActionArg> GenAction { get; set; }
|
||||||
|
|
||||||
|
|
||||||
public SnowWorkerM1(IdGeneratorOptions options)
|
public SnowWorkerM1(IdGeneratorOptions options)
|
||||||
{
|
{
|
||||||
WorkerId = options.WorkerId;
|
WorkerId = options.WorkerId;
|
||||||
@ -67,12 +79,11 @@ namespace Yitter.IdGenerator
|
|||||||
SeqBitLength = options.SeqBitLength;
|
SeqBitLength = options.SeqBitLength;
|
||||||
MaxSeqNumber = options.MaxSeqNumber;
|
MaxSeqNumber = options.MaxSeqNumber;
|
||||||
MinSeqNumber = options.MinSeqNumber;
|
MinSeqNumber = options.MinSeqNumber;
|
||||||
_CurrentSeqNumber = options.MinSeqNumber;
|
|
||||||
TopOverCostCount = options.TopOverCostCount;
|
TopOverCostCount = options.TopOverCostCount;
|
||||||
|
|
||||||
if (options.StartTime != DateTime.MinValue)
|
if (options.BaseTime != DateTime.MinValue)
|
||||||
{
|
{
|
||||||
StartTimeUtc = options.StartTime;
|
BaseTime = options.BaseTime;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WorkerId < 1)
|
if (WorkerId < 1)
|
||||||
@ -82,20 +93,24 @@ namespace Yitter.IdGenerator
|
|||||||
|
|
||||||
if (SeqBitLength == 0)
|
if (SeqBitLength == 0)
|
||||||
{
|
{
|
||||||
SeqBitLength = 10;
|
SeqBitLength = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WorkerIdBitLength == 0)
|
if (WorkerIdBitLength == 0)
|
||||||
{
|
{
|
||||||
WorkerIdBitLength = 10;
|
WorkerIdBitLength = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MaxSeqNumber == 0)
|
if (MaxSeqNumber == 0)
|
||||||
{
|
{
|
||||||
MaxSeqNumber = (int)Math.Pow(2, SeqBitLength);
|
MaxSeqNumber = (1 << SeqBitLength) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
_TimestampShift = (byte)(WorkerIdBitLength + SeqBitLength);
|
_TimestampShift = (byte)(WorkerIdBitLength + SeqBitLength);
|
||||||
|
_CurrentSeqNumber = options.MinSeqNumber;
|
||||||
|
|
||||||
|
//_BaseTimeTick = BaseTime.Ticks;
|
||||||
|
//_StartTimeTick = (long)(DateTime.UtcNow.Subtract(BaseTime).TotalMilliseconds) - Environment.TickCount;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -107,8 +122,10 @@ namespace Yitter.IdGenerator
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private void BeginOverCostCallBack(in long useTimeTick)
|
private void BeginOverCostAction(in long useTimeTick)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
|
||||||
if (GenAction == null)
|
if (GenAction == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -123,12 +140,13 @@ namespace Yitter.IdGenerator
|
|||||||
_TermIndex));
|
_TermIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void EndOverCostCallBack(in long useTimeTick)
|
private void EndOverCostAction(in long useTimeTick)
|
||||||
{
|
{
|
||||||
if (_TermIndex > 10000)
|
if (_TermIndex > 10000)
|
||||||
{
|
{
|
||||||
_TermIndex = 0;
|
_TermIndex = 0;
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
|
||||||
if (GenAction == null)
|
if (GenAction == null)
|
||||||
{
|
{
|
||||||
@ -144,8 +162,10 @@ namespace Yitter.IdGenerator
|
|||||||
_TermIndex));
|
_TermIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void TurnBackCallBack(in long useTimeTick)
|
private void BeginTurnBackAction(in long useTimeTick)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
|
||||||
if (GenAction == null)
|
if (GenAction == null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@ -155,9 +175,27 @@ namespace Yitter.IdGenerator
|
|||||||
WorkerId,
|
WorkerId,
|
||||||
useTimeTick,
|
useTimeTick,
|
||||||
8,
|
8,
|
||||||
_OverCostCountInOneTerm,
|
0,
|
||||||
_GenCountInOneTerm,
|
0,
|
||||||
_TermIndex));
|
_TurnBackIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EndTurnBackAction(in long useTimeTick)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (GenAction == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
DoGenIdAction(new OverCostActionArg(
|
||||||
|
WorkerId,
|
||||||
|
useTimeTick,
|
||||||
|
9,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
_TurnBackIndex));
|
||||||
}
|
}
|
||||||
|
|
||||||
private long NextOverCostId()
|
private long NextOverCostId()
|
||||||
@ -166,7 +204,7 @@ namespace Yitter.IdGenerator
|
|||||||
|
|
||||||
if (currentTimeTick > _LastTimeTick)
|
if (currentTimeTick > _LastTimeTick)
|
||||||
{
|
{
|
||||||
EndOverCostCallBack(currentTimeTick);
|
EndOverCostAction(currentTimeTick);
|
||||||
|
|
||||||
_LastTimeTick = currentTimeTick;
|
_LastTimeTick = currentTimeTick;
|
||||||
_CurrentSeqNumber = MinSeqNumber;
|
_CurrentSeqNumber = MinSeqNumber;
|
||||||
@ -179,7 +217,7 @@ namespace Yitter.IdGenerator
|
|||||||
|
|
||||||
if (_OverCostCountInOneTerm >= TopOverCostCount)
|
if (_OverCostCountInOneTerm >= TopOverCostCount)
|
||||||
{
|
{
|
||||||
EndOverCostCallBack(currentTimeTick);
|
EndOverCostAction(currentTimeTick);
|
||||||
|
|
||||||
_LastTimeTick = GetNextTimeTick();
|
_LastTimeTick = GetNextTimeTick();
|
||||||
_CurrentSeqNumber = MinSeqNumber;
|
_CurrentSeqNumber = MinSeqNumber;
|
||||||
@ -209,6 +247,34 @@ namespace Yitter.IdGenerator
|
|||||||
{
|
{
|
||||||
long currentTimeTick = GetCurrentTimeTick();
|
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)
|
if (currentTimeTick > _LastTimeTick)
|
||||||
{
|
{
|
||||||
_LastTimeTick = currentTimeTick;
|
_LastTimeTick = currentTimeTick;
|
||||||
@ -219,32 +285,18 @@ namespace Yitter.IdGenerator
|
|||||||
|
|
||||||
if (_CurrentSeqNumber > MaxSeqNumber)
|
if (_CurrentSeqNumber > MaxSeqNumber)
|
||||||
{
|
{
|
||||||
BeginOverCostCallBack(currentTimeTick);
|
BeginOverCostAction(currentTimeTick);
|
||||||
|
|
||||||
_TermIndex++;
|
_TermIndex++;
|
||||||
_LastTimeTick++;
|
_LastTimeTick++;
|
||||||
_CurrentSeqNumber = MinSeqNumber;
|
_CurrentSeqNumber = MinSeqNumber;
|
||||||
_IsOverCost = true;
|
_IsOverCost = true;
|
||||||
_OverCostCountInOneTerm++;
|
_OverCostCountInOneTerm = 1;
|
||||||
_GenCountInOneTerm = 1;
|
_GenCountInOneTerm = 1;
|
||||||
|
|
||||||
return CalcId(_LastTimeTick);
|
return CalcId(_LastTimeTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (currentTimeTick < _LastTimeTick)
|
|
||||||
{
|
|
||||||
if (_TurnBackTimeTick < 1)
|
|
||||||
{
|
|
||||||
_TurnBackTimeTick = _LastTimeTick - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Thread.Sleep(10);
|
|
||||||
TurnBackCallBack(_TurnBackTimeTick);
|
|
||||||
|
|
||||||
return CalcTurnBackId(_TurnBackTimeTick);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
return CalcId(_LastTimeTick);
|
return CalcId(_LastTimeTick);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -261,7 +313,7 @@ namespace Yitter.IdGenerator
|
|||||||
private long CalcTurnBackId(in long useTimeTick)
|
private long CalcTurnBackId(in long useTimeTick)
|
||||||
{
|
{
|
||||||
var result = ((useTimeTick << _TimestampShift) +
|
var result = ((useTimeTick << _TimestampShift) +
|
||||||
((long)WorkerId << SeqBitLength) + 0);
|
((long)WorkerId << SeqBitLength) + _TurnBackIndex);
|
||||||
|
|
||||||
_TurnBackTimeTick--;
|
_TurnBackTimeTick--;
|
||||||
return result;
|
return result;
|
||||||
@ -269,7 +321,9 @@ namespace Yitter.IdGenerator
|
|||||||
|
|
||||||
protected virtual long GetCurrentTimeTick()
|
protected virtual long GetCurrentTimeTick()
|
||||||
{
|
{
|
||||||
return (long)(DateTime.UtcNow - StartTimeUtc).TotalMilliseconds;
|
//return (long)(DateTime.UtcNow - BaseTime).Ticks;
|
||||||
|
//return (long)(_StartTimeTick + Environment.TickCount);
|
||||||
|
return (long)(DateTime.UtcNow - BaseTime).TotalMilliseconds;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual long GetNextTimeTick()
|
protected virtual long GetNextTimeTick()
|
@ -1,4 +1,13 @@
|
|||||||
using System;
|
/*
|
||||||
|
* 版权属于:yitter(yitter@126.com)
|
||||||
|
* 开源地址:https://gitee.com/yitter/idgenerator
|
||||||
|
* 版权协议:MIT
|
||||||
|
* 版权说明:只要保留本版权,你可以免费使用、修改、分发本代码。
|
||||||
|
* 免责条款:任何因为本代码产生的系统、法律、政治、宗教问题,均与版权所有者无关。
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
@ -1,11 +1,23 @@
|
|||||||
using System;
|
/*
|
||||||
|
* 版权属于:yitter(yitter@126.com)
|
||||||
|
* 开源地址:https://gitee.com/yitter/idgenerator
|
||||||
|
* 版权协议:MIT
|
||||||
|
* 版权说明:只要保留本版权,你可以免费使用、修改、分发本代码。
|
||||||
|
* 免责条款:任何因为本代码产生的系统、法律、政治、宗教问题,均与版权所有者无关。
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
|
||||||
namespace Yitter.IdGenerator
|
namespace Yitter.IdGenerator
|
||||||
{
|
{
|
||||||
public class YitIdGenerator : IIdGenerator
|
/// <summary>
|
||||||
|
/// 默认实现
|
||||||
|
/// </summary>
|
||||||
|
public class DefaultIdGenerator : IIdGenerator
|
||||||
{
|
{
|
||||||
private ISnowWorker _SnowWorker { get; set; }
|
private ISnowWorker _SnowWorker { get; set; }
|
||||||
|
|
||||||
@ -15,44 +27,49 @@ namespace Yitter.IdGenerator
|
|||||||
set => _SnowWorker.GenAction = value;
|
set => _SnowWorker.GenAction = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public YitIdGenerator(IdGeneratorOptions options)
|
|
||||||
|
public DefaultIdGenerator(IdGeneratorOptions options)
|
||||||
{
|
{
|
||||||
if (options == null)
|
if (options == null)
|
||||||
{
|
{
|
||||||
throw new ApplicationException("options error.");
|
throw new ApplicationException("options error.");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.StartTime > DateTime.Now)
|
if (options.BaseTime < DateTime.Now.AddYears(-50) || options.BaseTime > DateTime.Now)
|
||||||
{
|
{
|
||||||
throw new ApplicationException("StartTime error.");
|
throw new ApplicationException("BaseTime error.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (options.WorkerIdBitLength <= 0)
|
||||||
|
{
|
||||||
|
throw new ApplicationException("WorkerIdBitLength error.(range:[1, 21])");
|
||||||
|
}
|
||||||
if (options.SeqBitLength + options.WorkerIdBitLength > 22)
|
if (options.SeqBitLength + options.WorkerIdBitLength > 22)
|
||||||
{
|
{
|
||||||
throw new ApplicationException("error:WorkerIdBitLength + SeqBitLength <= 22");
|
throw new ApplicationException("error:WorkerIdBitLength + SeqBitLength <= 22");
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxWorkerIdNumber = Math.Pow(2, options.WorkerIdBitLength) - 1;
|
var maxWorkerIdNumber = (1 << options.WorkerIdBitLength) - 1;
|
||||||
if (options.WorkerId < 1 || options.WorkerId > maxWorkerIdNumber)
|
if (options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber)
|
||||||
{
|
{
|
||||||
throw new ApplicationException("WorkerId is error. (range:[1, " + maxWorkerIdNumber + "]");
|
throw new ApplicationException("WorkerId error. (range:[0, " + (maxWorkerIdNumber > 0 ? maxWorkerIdNumber : 63) + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.SeqBitLength < 2 || options.SeqBitLength > 21)
|
if (options.SeqBitLength < 2 || options.SeqBitLength > 21)
|
||||||
{
|
{
|
||||||
throw new ApplicationException("SeqBitLength is error. (range:[2, 21])");
|
throw new ApplicationException("SeqBitLength error. (range:[2, 21])");
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxSeqNumber = Math.Pow(2, options.SeqBitLength) - 1;
|
var maxSeqNumber = (1 << options.SeqBitLength) - 1;
|
||||||
if (options.MaxSeqNumber < 0 || options.MaxSeqNumber > maxSeqNumber)
|
if (options.MaxSeqNumber < 0 || options.MaxSeqNumber > maxSeqNumber)
|
||||||
{
|
{
|
||||||
throw new ApplicationException("MaxSeqNumber is error. (range:[1, " + maxSeqNumber + "]");
|
throw new ApplicationException("MaxSeqNumber error. (range:[1, " + maxSeqNumber + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
var maxValue = maxSeqNumber - 2;
|
var maxValue = maxSeqNumber;
|
||||||
if (options.MinSeqNumber < 5 || options.MinSeqNumber > maxValue)
|
if (options.MinSeqNumber < 1 || options.MinSeqNumber > maxValue)
|
||||||
{
|
{
|
||||||
throw new ApplicationException("MinSeqNumber is error. (range:[5, " + maxValue + "]");
|
throw new ApplicationException("MinSeqNumber error. (range:[1, " + maxValue + "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (options.Method)
|
switch (options.Method)
|
@ -1,11 +0,0 @@
|
|||||||
using System;
|
|
||||||
|
|
||||||
namespace Yitter.IdGenerator
|
|
||||||
{
|
|
||||||
public interface IIdGenerator
|
|
||||||
{
|
|
||||||
Action<OverCostActionArg> GenIdActionAsync { get; set; }
|
|
||||||
|
|
||||||
long NewLong();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Yitter.IdGenerator
|
|
||||||
{
|
|
||||||
internal interface ISnowWorker
|
|
||||||
{
|
|
||||||
Action<OverCostActionArg> GenAction { get; set; }
|
|
||||||
|
|
||||||
long NextId();
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,65 +0,0 @@
|
|||||||
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()
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
53
Infrastructure/Snowflake/YitIdHelper.cs
Normal file
53
Infrastructure/Snowflake/YitIdHelper.cs
Normal file
@ -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
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// 这是一个调用的例子,默认情况下,单机集成者可以直接使用 NextId()。
|
||||||
|
/// </summary>
|
||||||
|
public class YitIdHelper
|
||||||
|
{
|
||||||
|
private static IIdGenerator _IdGenInstance = null;
|
||||||
|
|
||||||
|
public static IIdGenerator IdGenInstance => _IdGenInstance;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 设置参数,建议程序初始化时执行一次
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="options"></param>
|
||||||
|
public static void SetIdGenerator(IdGeneratorOptions options)
|
||||||
|
{
|
||||||
|
_IdGenInstance = new DefaultIdGenerator(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// 生成新的Id
|
||||||
|
/// 调用本方法前,请确保调用了 SetIdGenerator 方法做初始化。
|
||||||
|
/// 否则将会初始化一个WorkerId为1的对象。
|
||||||
|
/// </summary>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static long NextId()
|
||||||
|
{
|
||||||
|
if (_IdGenInstance == null)
|
||||||
|
{
|
||||||
|
_IdGenInstance = new DefaultIdGenerator(
|
||||||
|
new IdGeneratorOptions() { WorkerId = 1 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return _IdGenInstance.NewLong();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
@ -11,14 +11,16 @@ namespace Infrastructure.Test
|
|||||||
public void Generate()
|
public void Generate()
|
||||||
{
|
{
|
||||||
// 全局初始化设置WorkerId,默认最大2^16-1。(初始化过程全局只需一次,且必须最先设置)
|
// 全局初始化设置WorkerId,默认最大2^16-1。(初始化过程全局只需一次,且必须最先设置)
|
||||||
var options = new IdGeneratorOptions(){ WorkerId = 1};
|
var options = new IdGeneratorOptions()
|
||||||
IIdGenerator IdHelper = new YitIdGenerator(options);
|
{
|
||||||
|
Method = 1,
|
||||||
|
WorkerId = 1
|
||||||
|
};
|
||||||
|
|
||||||
// 初始化以后,就可以在需要的地方调用方法生成ID。
|
YitIdHelper.SetIdGenerator(options);
|
||||||
long val =IdHelper.NewLong();
|
long newId = YitIdHelper.NextId();
|
||||||
int val2 = (int)val;
|
Console.WriteLine("=====================================");
|
||||||
|
Console.WriteLine("生成的 Id:" + newId);
|
||||||
Console.WriteLine($"val:{val}/int:{val2}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -39,19 +39,28 @@ namespace OpenAuth.App.Test
|
|||||||
[Test]
|
[Test]
|
||||||
public void Create()
|
public void Create()
|
||||||
{
|
{
|
||||||
var options = new IdGeneratorOptions(){ WorkerId = 1};
|
// 全局初始化设置WorkerId,默认最大2^16-1。(初始化过程全局只需一次,且必须最先设置)
|
||||||
IIdGenerator idHelper = new YitIdGenerator(options);
|
var options = new IdGeneratorOptions()
|
||||||
var code = idHelper.NewLong().ToString();
|
{
|
||||||
|
Method = 1,
|
||||||
|
WorkerId = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
YitIdHelper.SetIdGenerator(options);
|
||||||
|
var code = YitIdHelper.NextId().ToString();
|
||||||
|
|
||||||
var app = _autofacServiceProvider.GetService<FlowInstanceApp>();
|
var app = _autofacServiceProvider.GetService<FlowInstanceApp>();
|
||||||
app.CreateInstance(new AddFlowInstanceReq
|
var instanceReq = new AddFlowInstanceReq
|
||||||
{
|
{
|
||||||
SchemeId = "18a34903-175b-4cfb-9947-db67b538bbc8",
|
SchemeId = "0dac17c2-fec7-4bcd-a391-4ff74de8506a",
|
||||||
FrmType = 2,
|
FrmType = 1,
|
||||||
FrmData = "{\"WorkDate\":\"2021-03-15\",\"Time\":\"8\",\"Reason\":\"dsdsds\"}",
|
DbName = "FrmLeaveReq",
|
||||||
|
FrmData = "{\"id\":\"\",\"userName\":\"周翔宇\",\"requestType\":\"病假\",\"startDate\":\"2021-03-08T16:00:00.000Z\",\"startTime\":\"2021-03-16T15:11:28.000Z\",\"endDate\":\"2021-03-24T16:00:00.000Z\",\"endTime\":\"2021-03-16T15:11:31.000Z\",\"requestComment\":\"1111\",\"attachment\":\"\",\"files\":[],\"extendInfo\":\"\"}",
|
||||||
CustomName = DateTime.Now.ToString(),
|
CustomName = DateTime.Now.ToString(),
|
||||||
Code = code
|
Code = code
|
||||||
});
|
};
|
||||||
|
app.CreateInstance(instanceReq);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -61,7 +70,7 @@ namespace OpenAuth.App.Test
|
|||||||
var app = _autofacServiceProvider.GetService<FlowInstanceApp>();
|
var app = _autofacServiceProvider.GetService<FlowInstanceApp>();
|
||||||
app.Verification(new VerificationReq
|
app.Verification(new VerificationReq
|
||||||
{
|
{
|
||||||
FlowInstanceId = "c2d6d4b9-527d-426e-98db-1d5dc905a994",
|
FlowInstanceId = "12a99820-3762-40a7-9f0f-ad0f8a0aab2d",
|
||||||
VerificationFinally = "3"
|
VerificationFinally = "3"
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -16,17 +16,24 @@ namespace OpenAuth.Repository.Core
|
|||||||
return Id == 0;
|
return Id == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static LongEntity()
|
||||||
|
{
|
||||||
|
//设置参数,程序初始化时执行一次
|
||||||
|
var options = new IdGeneratorOptions()
|
||||||
|
{
|
||||||
|
Method = 1,
|
||||||
|
WorkerId = 1
|
||||||
|
};
|
||||||
|
|
||||||
|
YitIdHelper.SetIdGenerator(options);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 采用雪花算法计算Id
|
/// 采用雪花算法计算Id
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public override void GenerateDefaultKeyVal()
|
public override void GenerateDefaultKeyVal()
|
||||||
{
|
{
|
||||||
// 全局初始化设置WorkerId,默认最大2^16-1。(初始化过程全局只需一次,且必须最先设置)
|
Id = YitIdHelper.NextId();
|
||||||
var options = new IdGeneratorOptions(){ WorkerId = 1};
|
|
||||||
IIdGenerator IdHelper = new YitIdGenerator(options);
|
|
||||||
|
|
||||||
// 初始化以后,就可以在需要的地方调用方法生成ID。
|
|
||||||
Id = IdHelper.NewLong();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
Loading…
Reference in New Issue
Block a user