✨
This commit is contained in:
118
StopShopping.Services/Implementions/SerialNoGenerator.cs
Normal file
118
StopShopping.Services/Implementions/SerialNoGenerator.cs
Normal file
@@ -0,0 +1,118 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace StopShopping.Services.Implementions;
|
||||
|
||||
public class SerialNoGenerator : ISerialNoGenerator
|
||||
{
|
||||
public SerialNoGenerator(ILogger<SerialNoGenerator> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
private readonly ILogger<SerialNoGenerator> _logger;
|
||||
|
||||
private const long START_UTC = 1767196800000; //2026-01-01 00:00:00.000
|
||||
private const int BITS_CALLBACK = 3;
|
||||
private const int BITS_SERIAL = 6;
|
||||
private const long MASK_CALLBACK = ~(-1L << BITS_CALLBACK); //0b_0111
|
||||
private const long MASK_SERIAL = ~(-1L << BITS_SERIAL);
|
||||
|
||||
private readonly object _lockObj = new();
|
||||
|
||||
private long _lastUtc = DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||||
private long _serial;
|
||||
private long _callbackSerial;
|
||||
|
||||
/// <summary>
|
||||
/// <list type="table">
|
||||
/// <item>
|
||||
/// <term>
|
||||
/// 0000000
|
||||
/// </term>
|
||||
/// <term>
|
||||
/// 00000000000
|
||||
/// </term>
|
||||
/// <term>
|
||||
/// 00000000000
|
||||
/// </term>
|
||||
/// <term>
|
||||
/// 0000000000
|
||||
/// </term>
|
||||
/// </item>
|
||||
///
|
||||
/// <item>
|
||||
/// <term>
|
||||
/// 符号位1bit
|
||||
/// </term>
|
||||
/// </item>
|
||||
/// <term>
|
||||
/// 毫秒时间戳56bit
|
||||
/// </term>
|
||||
/// <term>
|
||||
/// 时间回拨标识3bit
|
||||
/// </term>
|
||||
/// <term>
|
||||
/// 毫秒内序号6bit
|
||||
/// </term>
|
||||
/// </list>
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public string GenerateRequestNo()
|
||||
{
|
||||
lock (_lockObj)
|
||||
{
|
||||
var currUtc = DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||||
|
||||
if (currUtc < _lastUtc) //时间回拨
|
||||
{
|
||||
currUtc = _lastUtc;
|
||||
_callbackSerial = (_callbackSerial + 1) & MASK_CALLBACK;
|
||||
if (_callbackSerial == 0) //时间回拨标识数据段用完
|
||||
{
|
||||
_logger.LogWarning("服务器时间不准,序列号可能重复,请检查!");
|
||||
}
|
||||
}
|
||||
|
||||
if (currUtc > _lastUtc)
|
||||
{
|
||||
_serial = 1;
|
||||
_callbackSerial = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
_serial = (_serial + 1) & MASK_SERIAL;
|
||||
if (_serial == 0) //毫秒内数据段用完
|
||||
{
|
||||
WaitNextMilliSecond(ref currUtc);
|
||||
_serial = 1;
|
||||
}
|
||||
}
|
||||
|
||||
_lastUtc = currUtc;
|
||||
|
||||
long serial = ((currUtc - START_UTC) << BITS_CALLBACK + BITS_SERIAL)
|
||||
| (_callbackSerial << BITS_SERIAL)
|
||||
| _serial;
|
||||
|
||||
return string.Format("R{0}", serial);
|
||||
}
|
||||
}
|
||||
|
||||
public string GenerateProductNo()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
private void WaitNextMilliSecond(ref long curr)
|
||||
{
|
||||
while (_lastUtc >= curr)
|
||||
{
|
||||
curr = DateTimeOffset.Now.ToUnixTimeMilliseconds();
|
||||
}
|
||||
}
|
||||
|
||||
public string GenerateRandomPassword()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user