118 lines
2.9 KiB
C#
118 lines
2.9 KiB
C#
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();
|
|
}
|
|
} |