# 雪花算法改进
**Repository Path**: Ray3390/SnowFlake
## Basic Information
- **Project Name**: 雪花算法改进
- **Description**: 雪花算法一个小改进
- **Primary Language**: C#
- **License**: MIT
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 0
- **Created**: 2019-12-19
- **Last Updated**: 2023-12-25
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# 雪花算法改进
#### 介绍
雪花算法的一个小改进,改进问题,当时间发生NTP回拨,会抛出异常。目前自己测试的没有问题,不保证所有场景能测试到。
如改进方法有误,希望及时留言,我会关闭该仓库,以免误人子弟。
如改进方法有误,希望及时留言,我会关闭该仓库,以免误人子弟。
如改进方法有误,希望及时留言,我会关闭该仓库,以免误人子弟。
#### 改进思想
利用未来时间弥补NTP回拨时间。
代码内记录了lastTimestamp(最后的时间戳),改进方法就是,如果发生NTP回拨,直接使用lastTimestamp产生id,如果1个毫秒内的id使用完了,直接lastTimestamp自动加1个毫秒,再继续生产,直至抵消回拨时间
#### 改进代码
```
///
/// 获取id
///
///
public long NextId()
{
lock (_lock)
{
var timestamp = TimeGen();
if (timestamp < lastTimestamp)
{
//修改此处,不再抛出异常
return NextNtpId();
//throw new Exception($"时间戳必须大于上一次生成ID的时间戳. 拒绝为{lastTimestamp - timestamp}毫秒生成id");
}
......
}
}
///
/// 产生NTP回拨id
///
///
protected virtual long NextNtpId()
{
//sequence自增,和sequenceMask相与一下,去掉高位
sequence = (sequence + 1) & MaxSequenceNum;
//判断是否溢出,也就是每毫秒内超过4095,当为4095时,与MaxSequenceNum相与,sequence就等于0
if (sequence == 0L)
{
//自动+1毫秒,用未来时间做弥补,直至补齐
lastTimestamp = lastTimestamp + 1;
}
return ((lastTimestamp - StartStmp) << TimestampLeftShift) |
(DatacenterId << DatacenterIdShift) |
(MachineId << MachineShift) |
sequence;
}
```
#### 未解决问题
和原始算法一样,当程序关闭后发生NTP回拨,仍然会产生重复id。目前我能想到的解决思想是:把lastTimestamp持久化,可以每个1秒持久化1次,当程序启动时直接赋值为持久化数据,这样可以更近一步减少重复id的发生几率。目前代码中没有实现。
#### 生产系统中需要注意的问题
雪花算法产生的id为long类型,返回给web前端时,如果数值过大,会造成js number类型精度丢失,一定要注意!!!