Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 25 additions & 16 deletions C#/source/Yitter.IdGenerator/Contract/IIdGenerator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,25 +5,34 @@
* 版权说明:只要保留本版权,你可以免费使用、修改、分发本代码。
* 免责条款:任何因为本代码产生的系统、法律、政治、宗教问题,均与版权所有者无关。
*
*/

using System;

namespace Yitter.IdGenerator
{
public interface IIdGenerator
{
*/
using System;
namespace Yitter.IdGenerator
{
public interface IIdGenerator
{
/// <summary>
/// 生成过程中产生的事件
/// </summary>
/// </summary>
//Action<OverCostActionArg> GenIdActionAsync { get; set; }

/// <summary>
/// 生成新的long型Id
/// </summary>
/// <returns></returns>
long NewLong();

// Guid NewGuid();
}
}
/// <returns></returns>
long NewLong();

// Guid NewGuid();


/// <summary>
/// 生成一个指定时间的 Id(时间用于构造时间差部分)
/// </summary>
/// <param name="dateTime">用于生成ID的时间(建议UTC或能正确转换为UTC的本地时间)</param>
/// <param name="isMillisecondPrecision">是否是毫秒级的时间</param>
/// <returns></returns>
long NextId(DateTime dateTime, bool isMillisecondPrecision = true);
}
}
8 changes: 8 additions & 0 deletions C#/source/Yitter.IdGenerator/Contract/ISnowWorker.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,13 @@ internal interface ISnowWorker
//Action<OverCostActionArg> GenAction { get; set; }

long NextId();

/// <summary>
/// 根据传入时间生成一个新的 Id
/// </summary>
/// <param name="dateTime"></param>
/// <param name="isMillisecondPrecision"></param>
/// <returns></returns>
long NextId(DateTime dateTime, bool isMillisecondPrecision);
}
}
153 changes: 114 additions & 39 deletions C#/source/Yitter.IdGenerator/Core/SnowWorkerM1.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,27 @@
* 版权说明:只要保留本版权,你可以免费使用、修改、分发本代码。
* 免责条款:任何因为本代码产生的系统、法律、政治、宗教问题,均与版权所有者无关。
*
*/

using System;
using System.Threading;
*/
using System;
using System.Threading;
using System.Threading.Tasks;

namespace Yitter.IdGenerator
{
/// <summary>
/// 雪花漂移算法
/// </summary>
internal class SnowWorkerM1 : ISnowWorker
namespace Yitter.IdGenerator
{
/// <summary>
/// 雪花漂移算法
/// </summary>
internal class SnowWorkerM1 : ISnowWorker
{
/// <summary>
/// 基础时间
/// </summary>
protected readonly DateTime BaseTime;
protected readonly DateTime BaseTime;

/// <summary>
/// 机器码
/// </summary>
/// <summary>
/// 机器码
/// </summary>
protected readonly ushort WorkerId = 0;

/// <summary>
Expand All @@ -40,7 +40,7 @@ internal class SnowWorkerM1 : ISnowWorker

/// <summary>
/// 最大序列数(含)
/// </summary>
/// </summary>
protected readonly int MaxSeqNumber = 0;

/// <summary>
Expand All @@ -57,13 +57,13 @@ internal class SnowWorkerM1 : ISnowWorker
protected static object _SyncLock = new object();

protected ushort _CurrentSeqNumber = 0;
protected long _LastTimeTick = 0; // -1L
protected long _TurnBackTimeTick = 0; // -1L;
protected byte _TurnBackIndex = 0;
protected bool _IsOverCost = false;
protected long _LastTimeTick = 0; // -1L
protected long _TurnBackTimeTick = 0; // -1L;
protected byte _TurnBackIndex = 0;
protected bool _IsOverCost = false;
protected int _OverCostCountInOneTerm = 0;

#if DEBUG
#if DEBUG
protected int _GenCountInOneTerm = 0;
protected int _TermIndex = 0;
#endif
Expand All @@ -73,8 +73,8 @@ internal class SnowWorkerM1 : ISnowWorker
//private static long _StartTimeTick = 0;
//private static long _BaseTimeTick = 0;


public SnowWorkerM1(IdGeneratorOptions options)
public SnowWorkerM1(IdGeneratorOptions options)
{
// 1.BaseTime
if (options.BaseTime != DateTime.MinValue)
Expand Down Expand Up @@ -119,17 +119,17 @@ public SnowWorkerM1(IdGeneratorOptions options)
MinSeqNumber = options.MinSeqNumber;

// 7.Others
TopOverCostCount = options.TopOverCostCount;
TopOverCostCount = options.TopOverCostCount;
//if (TopOverCostCount == 0)
//{
// TopOverCostCount = 2000;
//}

_TimestampShift = (byte)(WorkerIdBitLength + SeqBitLength);
_CurrentSeqNumber = options.MinSeqNumber;

//_BaseTimeTick = BaseTime.Ticks;
//_StartTimeTick = (long)(DateTime.UtcNow.Subtract(BaseTime).TotalMilliseconds) - Environment.TickCount;
_TimestampShift = (byte)(WorkerIdBitLength + SeqBitLength);
_CurrentSeqNumber = options.MinSeqNumber;
//_BaseTimeTick = BaseTime.Ticks;
//_StartTimeTick = (long)(DateTime.UtcNow.Subtract(BaseTime).TotalMilliseconds) - Environment.TickCount;
}

#if DEBUG
Expand All @@ -140,7 +140,7 @@ private void DoGenIdAction(OverCostActionArg arg)
{
GenAction(arg);
});
}
}

private void BeginOverCostAction(in long useTimeTick)
{
Expand Down Expand Up @@ -265,7 +265,7 @@ protected virtual long NextOverCostId()
return CalcId(_LastTimeTick);
}

protected virtual long NextNormalId()
protected virtual long NextNormalId()
{
long currentTimeTick = GetCurrentTimeTick();

Expand Down Expand Up @@ -346,11 +346,11 @@ protected virtual long CalcTurnBackId(long useTimeTick)
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 GetCurrentTimeTick()
{
//return (long)(DateTime.UtcNow - BaseTime).Ticks;
//return (long)(_StartTimeTick + Environment.TickCount);
return (long)(DateTime.UtcNow - BaseTime).TotalMilliseconds;
}

protected virtual long GetNextTimeTick()
Expand All @@ -374,6 +374,81 @@ public virtual long NextId()
{
return _IsOverCost ? NextOverCostId() : NextNormalId();
}
}
}
}
}


// 新增:用于历史发号的独立序列计数器
protected int _historySeqCounter = 0;

/// <summary>
///
/// </summary>
/// <param name="dateTime"></param>
/// <param name="isMillisecondPrecision"></param>
/// <returns></returns>
/// <exception cref="ArgumentOutOfRangeException"></exception>
public virtual long NextId(DateTime dateTime, bool isMillisecondPrecision)
{
// 如果没有毫秒精度,则用当前系统时间的毫秒值覆盖
if (!isMillisecondPrecision)
{
var nowMs = DateTime.UtcNow.Millisecond; // 0..999
dateTime = new DateTime(
dateTime.Year, dateTime.Month, dateTime.Day,
dateTime.Hour, dateTime.Minute, dateTime.Second,
nowMs, dateTime.Kind
);
}

// 计算与基准时间的毫秒差
var timeTick = ToTimeTick(dateTime);
if (timeTick < 0)
throw new ArgumentOutOfRangeException(nameof(dateTime), "指定时间早于 BaseTime。");
if (timeTick > GetMaxTimeTick())
throw new ArgumentOutOfRangeException(nameof(dateTime), "指定时间超过时间位宽上限。");

// 历史路径不影响实时状态:使用独立序列
var half = (MaxSeqNumber + 1) / 2;
var localSeq = Interlocked.Increment(ref _historySeqCounter);
var seq = half + (localSeq & (half - 1));
if (seq > MaxSeqNumber) seq &= MaxSeqNumber;

return CalcId(timeTick, seq); // 按时间差+WorkerId+序列号拼装:contentReference[oaicite:2]{index=2}
}

/// <summary>
/// 获取时间戳(相对于 BaseTime 的毫秒时间戳)
/// 将dateTime转换为UTC时间,并计算与BaseTime的毫秒差。
/// </summary>
/// <param name="dateTime"></param>
/// <returns></returns>
protected long ToTimeTick(DateTime dateTime)
{
// 以 BaseTime(毫秒时间戳)为基准换算
return (long)(dateTime.ToUniversalTime() - BaseTime).TotalMilliseconds;
}

/// <summary>
/// 获取最大时间戳(时间位宽上限)
/// </summary>
/// <returns></returns>
protected long GetMaxTimeTick()
{
int timestampBits = 63 - WorkerIdBitLength - SeqBitLength;
return (timestampBits >= 63) ? long.MaxValue : ((1L << timestampBits) - 1);
}

/// <summary>
///
/// </summary>
/// <param name="timeTick"></param>
/// <param name="seq"></param>
/// <returns></returns>
public virtual long CalcId(long timeTick, long seq)
{
return ((timeTick << _TimestampShift) +
((long)WorkerId << SeqBitLength) +
(uint)seq);
}
}
}
Loading