Files
2025-10-09 13:58:21 +08:00

91 lines
3.2 KiB
C#
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace VolPro.Core.Utilities
{
public class IdWorker
{
private static long machineId;
private static long datacenterId;
private static long sequence = 0L;
private static long twepoch = 1288834974657L;
private static long machineIdBits = 5L;
private static long datacenterIdBits = 5L;
private static long maxMachineId = -1L ^ (-1L << (int)machineIdBits);
private static long maxDatacenterId = -1L ^ (-1L << (int)datacenterIdBits);
private static long sequenceBits = 12L;
private static long machineIdShift = sequenceBits;
private static long datacenterIdShift = sequenceBits + machineIdBits;
private static long timestampLeftShift = sequenceBits + machineIdBits + datacenterIdBits;
private static long sequenceMask = -1L ^ (-1L << (int)sequenceBits);
private static long lastTimestamp = -1L;
private static object lockSnowObj = new object();
public IdWorker(long machineId = 1, long datacenterId = 1)
{
if (machineId > maxMachineId || machineId < 0)
{
throw new Exception("machineId can't be greater than maxMachineId or less than 0");
}
if (datacenterId > maxDatacenterId || datacenterId < 0)
{
throw new Exception("datacenterId can't be greater than maxDatacenterId or less than 0");
}
IdWorker.machineId = machineId;
IdWorker.datacenterId = datacenterId;
}
public long NextId()
{
lock (lockSnowObj)
{
long timestamp = TimeGen();
if (timestamp < lastTimestamp)
{
throw new Exception("Clock moved backwards. Refusing to generate id for " + (lastTimestamp - timestamp) + " milliseconds");
}
if (lastTimestamp == timestamp)
{
sequence = (sequence + 1) & sequenceMask;
if (sequence == 0)
{
// 如果在同一毫秒内生成的ID数量超过了限制等待下一毫秒
timestamp = TilNextMillis(lastTimestamp);
}
}
else
{
sequence = 0L;
}
lastTimestamp = timestamp;
return ((timestamp - twepoch) << (int)timestampLeftShift) |
(datacenterId << (int)datacenterIdShift) |
(machineId << (int)machineIdShift) |
sequence;
}
}
private long TilNextMillis(long lastTimestamp)
{
long timestamp = TimeGen();
while (timestamp <= lastTimestamp)
{
timestamp = TimeGen();
}
return timestamp;
}
private long TimeGen()
{
return (long)(DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalMilliseconds;
}
}
}