snowflake-csharp
snowflake-csharp copied to clipboard
无法产生id
环境是.net 9 ,直接用源代码测试的,会在while 内产生死循环
using System; using System.Threading;
namespace Snowflake
{
///
/// <summary>
/// 每一部分占用的位数
/// </summary>
private const int SequenceBit = 12; //序列号占用的位数
private const int MachineBit = 6; //机器标识占用的位数
private const int DatacenterBit = 6;//数据中心占用的位数
/// <summary>
/// 每一部分的最大值
/// </summary>
private const int MaxDatacenterNum = -1 ^ (-1 << DatacenterBit);
private const int MaxMachineNum = -1 ^ (-1 << MachineBit);
private const int MaxSequence = -1 ^ (-1 << SequenceBit);
/// <summary>
/// 每一部分向左的位移
/// </summary>
private const int MachineLeft = SequenceBit;
private const int DatacenterLeft = SequenceBit + MachineBit;
private const int TimestampLeft = DatacenterLeft + DatacenterBit;
private readonly long _datacenterId; //数据中心
private static long _machineId; //机器标识
private long _sequence; //序列号
private long _lastStamp = -1L;//上一次时间戳
public SnowFlake(long datacenterId, long machineId)
{
if (datacenterId > MaxDatacenterNum || datacenterId < 0)
{
throw new ArgumentException("datacenterId can't be greater than MAX_DATACENTER_NUM or less than 0");
}
if (machineId > MaxMachineNum || machineId < 0)
{
throw new ArgumentException("machineId can't be greater than MAX_MACHINE_NUM or less than 0");
}
_datacenterId = datacenterId;
_machineId = machineId;
}
///// <summary>
///// 产生下一个ID
///// </summary>
///// <returns></returns>
//public virtual long NextId()
//{
// while (true)
// {
// long timestamp = GetNewStamp();
// if (timestamp < _lastStamp)
// {
// //时钟回拨,更新为上一次生成id的时间戳
// timestamp = _lastStamp;
// }
// if (_lastStamp == timestamp)
// {
// //相同毫秒内,序列号自增
// _sequence = (_sequence + 1) & MaxSequence;
// //同一毫秒的序列数已经达到最大
// if (_sequence == 0L)
// {
// SpinWait.SpinUntil(() => GetNewStamp() > _lastStamp);
// continue;
// }
// }
// else
// {
// //不同毫秒内,序列号置为0
// _sequence = 0L;
// }
// if (Interlocked.CompareExchange(ref _lastStamp, timestamp, _lastStamp) != timestamp)
// {
// continue;
// }
// // Bits for timestamp, data center, machine identifier, and sequence number
// return ((timestamp - StartStamp) << TimestampLeft)
// | (_datacenterId << DatacenterLeft)
// | (_machineId << MachineLeft)
// | _sequence;
// }
//}
public virtual long NextNewId()
{
while (true)
{
long timestamp = GetNewStamp();
if (timestamp < _lastStamp)
{
// 时钟回拨,更新为上一次生成id的时间戳
timestamp = _lastStamp;
}
if (_lastStamp == timestamp)
{
// 相同毫秒内,序列号自增
_sequence = (_sequence + 1) & MaxSequence;
// 同一毫秒的序列数已经达到最大
if (_sequence == 0L)
{
// 等待下一个时间戳
SpinWait.SpinUntil(() => (timestamp = GetNewStamp()) > _lastStamp);
}
}
else
{
// 不同毫秒内,序列号置为0
_sequence = 0L;
}
// 比较并更新 _lastStamp。只有在 _lastStamp 等于当前的 timestamp 时,才进行更新
long originalLastStamp = Interlocked.CompareExchange(ref _lastStamp, timestamp, _lastStamp);
if (originalLastStamp == _lastStamp)
{
// 成功更新时间戳,生成ID并返回
return ((timestamp - StartStamp) << TimestampLeft)
| (_datacenterId << DatacenterLeft)
| (_machineId << MachineLeft)
| _sequence;
}
}
}
protected virtual long GetNextMill()
{
long mill = GetNewStamp();
while (mill <= _lastStamp)
{
mill = GetNewStamp();
}
return mill;
}
public static void SetMachineId(long machineId)
{
_machineId = machineId;
}
public long GetMachineId()
{
return _machineId;
}
protected virtual long GetNewStamp()
{
return System.CurrentTimeMillis();
}
}
} 这是我改的