@@ -20,57 +20,7 @@ var newId = IdHelper.NextId(); | |||
``` | |||
如果基于DI框架集成,可以参考 IdHelper 去管理 IdGenerator 对象,必须使用**单例**模式。 | |||
## options说明 | |||
``` | |||
public class IdGeneratorOptions | |||
{ | |||
/// <summary> | |||
/// 雪花计算方法 | |||
/// (1|2) | |||
/// </summary> | |||
public short Method { get; set; } = 1; | |||
/// <summary> | |||
/// 开始时间(UTC格式) | |||
/// 不能超过当前系统时间 | |||
/// </summary> | |||
public DateTime StartTime { get; set; } = DateTime.MinValue; | |||
/// <summary> | |||
/// 机器码 | |||
/// 与 WorkerIdBitLength 有关系 | |||
/// </summary> | |||
public ushort WorkerId { get; set; } = 0; | |||
/// <summary> | |||
/// 机器码位长 | |||
/// 范围:2-21(要求:序列数位长+机器码位长不超过22)。 | |||
/// 建议范围:6-12。 | |||
/// </summary> | |||
public byte WorkerIdBitLength { get; set; } = 6; | |||
/// <summary> | |||
/// 序列数位长 | |||
/// 范围:2-21(要求:序列数位长+机器码位长不超过22)。 | |||
/// 建议范围:6-14。 | |||
/// </summary> | |||
public byte SeqBitLength { get; set; } = 6; | |||
/// <summary> | |||
/// 最大序列数(含) | |||
/// (由SeqBitLength计算的最大值) | |||
/// </summary> | |||
public int MaxSeqNumber { get; set; } = 0; | |||
## options 默认值及说明 | |||
/// <summary> | |||
/// 最小序列数(含) | |||
/// 默认11,不小于5,不大于MaxSeqNumber-2 | |||
/// </summary> | |||
public ushort MinSeqNumber { get; set; } = 11; | |||
参考源码:/Contract/IdGeneratorOptions.cs | |||
/// <summary> | |||
/// 最大漂移次数(含), | |||
/// 默认2000,推荐范围500-10000(与计算能力有关) | |||
/// </summary> | |||
public int TopOverCostCount { get; set; } = 2000; | |||
``` |
@@ -50,7 +50,7 @@ namespace Yitter.OrgSystem.TestA | |||
//MinSeqNumber = 11, | |||
//MaxSeqNumber = 200, | |||
StartTime = DateTime.Now.AddYears(-10), | |||
BaseTime = DateTime.Now.AddYears(-10), | |||
}; | |||
// ++++++++++++++++++++++++++++++++ | |||
@@ -25,7 +25,7 @@ namespace Yitter.IdGenerator | |||
/// 开始时间(UTC格式) | |||
/// 不能超过当前系统时间 | |||
/// </summary> | |||
public virtual DateTime StartTime { get; set; } = DateTime.MinValue; | |||
public virtual DateTime BaseTime { get; set; } = new DateTime(2020, 2, 20, 2, 20, 2, 20, DateTimeKind.Utc); | |||
/// <summary> | |||
/// 机器码 | |||
@@ -21,7 +21,7 @@ namespace Yitter.IdGenerator | |||
/// <summary> | |||
/// 基础时间 | |||
/// </summary> | |||
protected readonly DateTime StartTimeUtc = new DateTime(2020, 2, 20, 2, 20, 2, 20, DateTimeKind.Utc); | |||
protected readonly DateTime BaseTime; | |||
/// <summary> | |||
/// 机器码 | |||
@@ -78,9 +78,9 @@ namespace Yitter.IdGenerator | |||
MinSeqNumber = options.MinSeqNumber; | |||
TopOverCostCount = options.TopOverCostCount; | |||
if (options.StartTime != DateTime.MinValue) | |||
if (options.BaseTime != DateTime.MinValue) | |||
{ | |||
StartTimeUtc = options.StartTime; | |||
BaseTime = options.BaseTime; | |||
} | |||
if (WorkerId < 1) | |||
@@ -278,7 +278,7 @@ namespace Yitter.IdGenerator | |||
protected virtual long GetCurrentTimeTick() | |||
{ | |||
return (long)(DateTime.UtcNow - StartTimeUtc).TotalMilliseconds; | |||
return (long)(DateTime.UtcNow - BaseTime).TotalMilliseconds; | |||
} | |||
protected virtual long GetNextTimeTick() | |||
@@ -35,9 +35,9 @@ namespace Yitter.IdGenerator | |||
throw new ApplicationException("options error."); | |||
} | |||
if (options.StartTime > DateTime.Now) | |||
if (options.BaseTime < DateTime.Now.AddYears(-50) || options.BaseTime > DateTime.Now) | |||
{ | |||
throw new ApplicationException("StartTime error."); | |||
throw new ApplicationException("BaseTime error."); | |||
} | |||
if (options.SeqBitLength + options.WorkerIdBitLength > 22) | |||
@@ -18,7 +18,7 @@ | |||
<Copyright>Yitter</Copyright> | |||
<PackageProjectUrl>https://gitee.com/yitter/idgenerator</PackageProjectUrl> | |||
<PackageLicenseExpression>MIT</PackageLicenseExpression> | |||
<Version>1.0.3</Version> | |||
<Version>1.0.6</Version> | |||
<PackageReleaseNotes></PackageReleaseNotes> | |||
</PropertyGroup> | |||
@@ -1,7 +1,7 @@ | |||
## 运行环境 | |||
JDK 1.8 | |||
JDK 1.8+ | |||
## 引用 maven 包 | |||
``` | |||
@@ -21,56 +21,8 @@ long newId = IdHelper.nextId(); | |||
``` | |||
如果基于DI框架集成,可以参考 IdHelper 去管理 IdGenerator 对象,必须使用**单例**模式。 | |||
## options说明 | |||
``` | |||
/** | |||
* 雪花计算方法 | |||
* (1-漂移算法|2-传统算法),默认1 | |||
*/ | |||
public short Method = 1; | |||
/** | |||
* 开始时间 | |||
* 不能超过当前系统时间 | |||
*/ | |||
public long StartTime = 0; | |||
/** | |||
* 机器码,必须由外部系统设置 | |||
* 与 WorkerIdBitLength 有关系 | |||
*/ | |||
public short WorkerId = 0; | |||
/** | |||
* 机器码位长 | |||
* 范围:2-21(要求:序列数位长+机器码位长不超过22)。 | |||
* 建议范围:6-12。 | |||
*/ | |||
public byte WorkerIdBitLength = 6; | |||
/** | |||
* 序列数位长 | |||
* 范围:2-21(要求:序列数位长+机器码位长不超过22)。 | |||
* 建议范围:6-14。 | |||
*/ | |||
public byte SeqBitLength = 6; | |||
/** | |||
* 最大序列数(含) | |||
* (由SeqBitLength计算的最大值) | |||
*/ | |||
public short MaxSeqNumber = 0; | |||
/** | |||
* 最小序列数(含) | |||
* 默认11,不小于5,不大于MaxSeqNumber-2 | |||
*/ | |||
public short MinSeqNumber = 11; | |||
## options 默认值及说明 | |||
/** | |||
* 最大漂移次数(含) | |||
* 默认2000,推荐范围500-10000(与计算能力有关) | |||
*/ | |||
public short TopOverCostCount = 2000; | |||
参考源码:/contract/IdGeneratorOptions.java | |||
``` |
@@ -20,7 +20,7 @@ public class IdGeneratorOptions { | |||
* 开始时间 | |||
* 不能超过当前系统时间 | |||
*/ | |||
public long StartTime = 0; | |||
public long BaseTime = 1582136402000L; | |||
/** | |||
* 机器码,必须由外部系统设置 | |||
@@ -14,7 +14,7 @@ public class SnowWorkerM1 implements ISnowWorker { | |||
/** | |||
* 基础时间 | |||
*/ | |||
protected final long StartTimeUtc; | |||
protected final long BaseTime; | |||
/** | |||
* 机器码 | |||
@@ -67,7 +67,7 @@ public class SnowWorkerM1 implements ISnowWorker { | |||
MaxSeqNumber = options.MaxSeqNumber > 0 ? options.MaxSeqNumber : (int) Math.pow(2, SeqBitLength); | |||
MinSeqNumber = options.MinSeqNumber; | |||
TopOverCostCount = options.TopOverCostCount; | |||
StartTimeUtc = options.StartTime != 0 ? options.StartTime : 1582136402000L; | |||
BaseTime = options.BaseTime != 0 ? options.BaseTime : 1582136402000L; | |||
_TimestampShift = (byte) (WorkerIdBitLength + SeqBitLength); | |||
_CurrentSeqNumber = options.MinSeqNumber; | |||
} | |||
@@ -224,7 +224,7 @@ public class SnowWorkerM1 implements ISnowWorker { | |||
protected long GetCurrentTimeTick() { | |||
long millis = System.currentTimeMillis(); | |||
return millis - StartTimeUtc; | |||
return millis - BaseTime; | |||
} | |||
protected long GetNextTimeTick() { | |||
@@ -17,46 +17,38 @@ public class DefaultIdGenerator implements IIdGenerator { | |||
private final ISnowWorker _SnowWorker; | |||
public DefaultIdGenerator(IdGeneratorOptions options) throws IdGeneratorException { | |||
if (options == null) | |||
{ | |||
if (options == null) { | |||
throw new IdGeneratorException("options error."); | |||
} | |||
if (options.StartTime > System.currentTimeMillis()) | |||
{ | |||
throw new IdGeneratorException("StartTime error."); | |||
if (options.BaseTime < 315504000000L || options.BaseTime > System.currentTimeMillis()) { | |||
throw new IdGeneratorException("BaseTime error."); | |||
} | |||
if (options.SeqBitLength + options.WorkerIdBitLength > 22) | |||
{ | |||
if (options.SeqBitLength + options.WorkerIdBitLength > 22) { | |||
throw new IdGeneratorException("error:WorkerIdBitLength + SeqBitLength <= 22"); | |||
} | |||
double maxWorkerIdNumber = Math.pow(2, options.WorkerIdBitLength) - 1; | |||
if (options.WorkerId < 1 || options.WorkerId > maxWorkerIdNumber) | |||
{ | |||
if (options.WorkerId < 1 || options.WorkerId > maxWorkerIdNumber) { | |||
throw new IdGeneratorException("WorkerId error. (range:[1, " + maxWorkerIdNumber + "]"); | |||
} | |||
if (options.SeqBitLength < 2 || options.SeqBitLength > 21) | |||
{ | |||
if (options.SeqBitLength < 2 || options.SeqBitLength > 21) { | |||
throw new IdGeneratorException("SeqBitLength error. (range:[2, 21])"); | |||
} | |||
double maxSeqNumber = Math.pow(2, options.SeqBitLength) - 1; | |||
if (options.MaxSeqNumber < 0 || options.MaxSeqNumber > maxSeqNumber) | |||
{ | |||
if (options.MaxSeqNumber < 0 || options.MaxSeqNumber > maxSeqNumber) { | |||
throw new IdGeneratorException("MaxSeqNumber error. (range:[1, " + maxSeqNumber + "]"); | |||
} | |||
double maxValue = maxSeqNumber - 2; | |||
if (options.MinSeqNumber < 5 || options.MinSeqNumber > maxValue) | |||
{ | |||
if (options.MinSeqNumber < 5 || options.MinSeqNumber > maxValue) { | |||
throw new IdGeneratorException("MinSeqNumber error. (range:[5, " + maxValue + "]"); | |||
} | |||
switch (options.Method) | |||
{ | |||
switch (options.Method) { | |||
case 1: | |||
_SnowWorker = new SnowWorkerM1(options); | |||
break; | |||
@@ -68,8 +60,7 @@ public class DefaultIdGenerator implements IIdGenerator { | |||
break; | |||
} | |||
if (options.Method == 1) | |||
{ | |||
if (options.Method == 1) { | |||
try { | |||
Thread.sleep(500); | |||
} catch (InterruptedException e) { | |||
@@ -79,7 +70,7 @@ public class DefaultIdGenerator implements IIdGenerator { | |||
} | |||
@Override | |||
public long newLong() { | |||
public long newLong() { | |||
return _SnowWorker.nextId(); | |||
} | |||
} |
@@ -1,12 +1,15 @@ | |||
package com.yitter.test; | |||
import com.yitter.contract.IIdGenerator; | |||
import java.util.HashSet; | |||
import java.util.Set; | |||
public class GenTest { | |||
private IIdGenerator IdGen; | |||
private int GenIdCount; | |||
private int WorkerId; | |||
private Set IdSet = new HashSet(); | |||
public GenTest(IIdGenerator idGen, int genIdCount, int workerId) { | |||
GenIdCount = genIdCount; | |||
@@ -19,6 +22,7 @@ public class GenTest { | |||
for (int i = 0; i < GenIdCount; i++) { | |||
long id = IdGen.newLong(); | |||
// IdSet.add(id); | |||
} | |||
long end = System.currentTimeMillis(); | |||
@@ -31,7 +31,7 @@ public class StartUp { | |||
// options.MaxSeqNumber = 200; | |||
options.Method = method; | |||
options.StartTime = 1582206693000L; // (2020-2-20) | |||
options.BaseTime = 1582206693000L; | |||
options.WorkerId = 1; | |||
IIdGenerator IdGen = new DefaultIdGenerator(options); | |||
@@ -1,8 +1,9 @@ | |||
# IdGenerator | |||
## 介绍 | |||
用一种全新的雪花漂移算法,让ID更短、生成速度更快。 | |||
核心在于缩短ID长度的同时,还能拥有极高瞬时并发处理量(50W/0.1s),及强大的配置能力。 | |||
用一种全新的雪花漂移算法,让ID更短、生成速度更快。 | |||
核心在于缩短ID长度的同时,还能拥有极高瞬时并发处理量(50W/0.1s)。 | |||
顶尖优化,超强效能(位数更短,速度更快),全新 SnowFlake 算法,支持 C#/Java/Go/PHP 等语言。 | |||
## 需求来源 | |||
@@ -138,7 +139,7 @@ | |||
配置变更指是系统运行一段时间后,再变更运行参数(IdGeneratorOptions选项值),请注意: | |||
1.最重要的一条原则是:StartTime **只能往前**(比老值更小、距离现在更远)赋值,原因是往后赋值极大可能产生相同的时间戳。[**不推荐**在系统运行之后调整 StartTime] | |||
1.最重要的一条原则是:BaseTime **只能往前**(比老值更小、距离现在更远)赋值,原因是往后赋值极大可能产生相同的时间戳。[**不推荐**在系统运行之后调整 BaseTime] | |||
2.任何时候增加 WorkerIdBitLength 或 SeqBitLength,都是可以的,但是慎用 “减小”的操作,因为这可能导致在未来某天生成的 ID 与过去老配置时相同。[允许在系统运行之后**增加**任何一个 BitLength 值] | |||