# Conflicts: # Go/regworkerid/regworkerid/reghelper.go # Go/source/main.gopull/19/MERGE
@@ -7,6 +7,7 @@ | |||||
*.userosscache | *.userosscache | ||||
*.sln.docstates | *.sln.docstates | ||||
*.editorconfig | *.editorconfig | ||||
__*.bat | |||||
# User-specific files (MonoDevelop/Xamarin Studio) | # User-specific files (MonoDevelop/Xamarin Studio) | ||||
*.userprefs | *.userprefs | ||||
@@ -1,7 +1,7 @@ | |||||
| | ||||
Microsoft Visual Studio Solution File, Format Version 12.00 | Microsoft Visual Studio Solution File, Format Version 12.00 | ||||
# Visual Studio Version 16 | |||||
VisualStudioVersion = 16.0.31005.135 | |||||
# Visual Studio Version 17 | |||||
VisualStudioVersion = 17.2.32602.215 | |||||
MinimumVisualStudioVersion = 10.0.40219.1 | MinimumVisualStudioVersion = 10.0.40219.1 | ||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yitter.IdGenerator", "Yitter.IdGenerator\Yitter.IdGenerator.csproj", "{FF8DAF11-34E7-4842-ADF2-3722A1A5FBB2}" | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yitter.IdGenerator", "Yitter.IdGenerator\Yitter.IdGenerator.csproj", "{FF8DAF11-34E7-4842-ADF2-3722A1A5FBB2}" | ||||
EndProject | EndProject | ||||
@@ -1,5 +1,6 @@ | |||||
using System; | using System; | ||||
using System.Collections; | using System.Collections; | ||||
using System.Collections.Concurrent; | |||||
using System.Collections.Generic; | using System.Collections.Generic; | ||||
using System.Runtime.InteropServices; | using System.Runtime.InteropServices; | ||||
using System.Threading; | using System.Threading; | ||||
@@ -11,7 +12,7 @@ namespace Yitter.OrgSystem.TestA | |||||
class Program | class Program | ||||
{ | { | ||||
// 测试参数(默认配置下,最佳性能是10W/s) | // 测试参数(默认配置下,最佳性能是10W/s) | ||||
static int genIdCount = 2;//50000; // 计算ID数量(如果要验证50W效率,请将TopOverCostCount设置为20000或适当增加SeqBitLength) | |||||
static int genIdCount = 50000;//5000; // 计算ID数量(如果要验证50W效率,请将TopOverCostCount设置为2000或适当增加SeqBitLength) | |||||
static short method = 1; // 1-漂移算法,2-传统算法 | static short method = 1; // 1-漂移算法,2-传统算法 | ||||
@@ -26,23 +27,24 @@ namespace Yitter.OrgSystem.TestA | |||||
static void Main(string[] args) | static void Main(string[] args) | ||||
{ | { | ||||
RunSingle(); | |||||
return; | |||||
Console.WriteLine("Hello World! C#"); | Console.WriteLine("Hello World! C#"); | ||||
var options = new IdGeneratorOptions() | var options = new IdGeneratorOptions() | ||||
{ | { | ||||
Method = method, | |||||
Method = 1, | |||||
WorkerId = 1, | WorkerId = 1, | ||||
WorkerIdBitLength = 6, | WorkerIdBitLength = 6, | ||||
SeqBitLength = 6, | SeqBitLength = 6, | ||||
DataCenterIdBitLength = 10, | |||||
DataCenterIdBitLength = 0, | |||||
TopOverCostCount = 2000, | TopOverCostCount = 2000, | ||||
//TimestampType = 1, | //TimestampType = 1, | ||||
// MinSeqNumber = 1, | // MinSeqNumber = 1, | ||||
// MaxSeqNumber = 200, | // MaxSeqNumber = 200, | ||||
// BaseTime = DateTime.Now.AddYears(-10), | // BaseTime = DateTime.Now.AddYears(-10), | ||||
}; | }; | ||||
@@ -55,27 +57,118 @@ namespace Yitter.OrgSystem.TestA | |||||
Console.WriteLine("====================================="); | Console.WriteLine("====================================="); | ||||
Console.WriteLine("这是用方法 " + method + " 生成的 Id:" + newId); | Console.WriteLine("这是用方法 " + method + " 生成的 Id:" + newId); | ||||
while (true) | |||||
var seed1 = 50; | |||||
var seed2 = 1000; | |||||
var finish = 0; | |||||
var next = IdGen.NewLong(); | |||||
var hashSet = new HashSet<long>(seed1 * seed2); | |||||
ConcurrentBag<long> bags = new ConcurrentBag<long>(); | |||||
for (int i = 0; i < seed1; i++) | |||||
{ | |||||
(new Thread(_ => | |||||
{ | |||||
for (int j = 0; j < seed2; j++) | |||||
{ | |||||
var me = IdGen.NewLong(); | |||||
hashSet.Add(me); | |||||
bags.Add(me); | |||||
} | |||||
Interlocked.Increment(ref finish); | |||||
}) | |||||
{ IsBackground = true }).Start(); | |||||
} | |||||
while (finish < seed1) | |||||
{ | { | ||||
RunSingle(); | |||||
//CallDll(); | |||||
//Go(options); | |||||
Thread.Sleep(1000); // 每隔1秒执行一次Go | |||||
Console.WriteLine("等待执行结束"); | |||||
Thread.Sleep(2000); | |||||
} | } | ||||
Console.WriteLine($"hashSet 共计:{hashSet.Count} 实际应该:{seed1 * seed2}"); | |||||
Console.WriteLine($"bags 共计:{bags.Count} 实际应该:{seed1 * seed2}"); | |||||
var IdArray = bags.ToArray(); | |||||
int totalCount = 0; | |||||
for (int i = 0; i < seed1 * seed2; i++) | |||||
{ | |||||
var me = IdArray[i]; | |||||
int j = 0; | |||||
int count = 0; | |||||
while (j < seed1 * seed2) | |||||
{ | |||||
if (IdArray[j] == me) | |||||
{ | |||||
count++; | |||||
} | |||||
j++; | |||||
} | |||||
if (count > 1) | |||||
{ | |||||
totalCount++; | |||||
Console.WriteLine($"{IdArray[i]},重复:{count}"); | |||||
} | |||||
} | |||||
if (totalCount == 0) | |||||
{ | |||||
Console.WriteLine($"重复数为 0 "); | |||||
} | |||||
Console.Read(); | |||||
//while (true) | |||||
//{ | |||||
// //RunSingle(); | |||||
// //CallDll(); | |||||
// //Go(options); | |||||
// Thread.Sleep(1000); // 每隔1秒执行一次Go | |||||
//} | |||||
} | } | ||||
private static void RunSingle() | private static void RunSingle() | ||||
{ | { | ||||
DateTime start = DateTime.Now; | |||||
for (int i = 0; i < genIdCount; i++) | |||||
var options = new IdGeneratorOptions() | |||||
{ | { | ||||
var id = IdGen.NewLong(); | |||||
} | |||||
Method = 1, | |||||
WorkerId = 1, | |||||
//WorkerIdBitLength = 6, | |||||
SeqBitLength = 6, | |||||
//TopOverCostCount = 2000, | |||||
//DataCenterIdBitLength = 0, | |||||
//TimestampType = 1, | |||||
// MinSeqNumber = 1, | |||||
// MaxSeqNumber = 200, | |||||
// BaseTime = DateTime.Now.AddYears(-10), | |||||
}; | |||||
DateTime end = DateTime.Now; | |||||
Console.WriteLine($"++++++++++++++++++++++++++++++++++++++++, total: {(end - start).TotalMilliseconds} ms"); | |||||
Interlocked.Increment(ref Program.Count); | |||||
//IdGen = new DefaultIdGenerator(options); | |||||
YitIdHelper.SetIdGenerator(options); | |||||
while (true) | |||||
{ | |||||
DateTime start = DateTime.Now; | |||||
for (int i = 0; i < genIdCount; i++) | |||||
{ | |||||
//var id = IdGen.NewLong(); | |||||
var id = YitIdHelper.NextId(); | |||||
} | |||||
DateTime end = DateTime.Now; | |||||
Console.WriteLine($"++++++++++++++++++++++++++++++++++++++++, total: {(end - start).TotalMilliseconds} ms"); | |||||
Thread.Sleep(1000); | |||||
} | |||||
//Interlocked.Increment(ref Program.Count); | |||||
} | } | ||||
private static void Go(IdGeneratorOptions options) | private static void Go(IdGeneratorOptions options) | ||||
@@ -2,7 +2,7 @@ | |||||
<PropertyGroup> | <PropertyGroup> | ||||
<OutputType>Exe</OutputType> | <OutputType>Exe</OutputType> | ||||
<TargetFramework>net5.0</TargetFramework> | |||||
<TargetFramework>net6.0</TargetFramework> | |||||
</PropertyGroup> | </PropertyGroup> | ||||
<PropertyGroup> | <PropertyGroup> | ||||
@@ -63,7 +63,6 @@ namespace Yitter.IdGenerator | |||||
/// </summary> | /// </summary> | ||||
public virtual int TopOverCostCount { get; set; } = 2000; | public virtual int TopOverCostCount { get; set; } = 2000; | ||||
/// <summary> | /// <summary> | ||||
/// 数据中心ID(默认0) | /// 数据中心ID(默认0) | ||||
/// </summary> | /// </summary> | ||||
@@ -118,10 +118,10 @@ namespace Yitter.IdGenerator | |||||
// 7.Others | // 7.Others | ||||
TopOverCostCount = options.TopOverCostCount; | TopOverCostCount = options.TopOverCostCount; | ||||
if (TopOverCostCount == 0) | |||||
{ | |||||
TopOverCostCount = 2000; | |||||
} | |||||
//if (TopOverCostCount == 0) | |||||
//{ | |||||
// TopOverCostCount = 2000; | |||||
//} | |||||
_TimestampShift = (byte)(WorkerIdBitLength + SeqBitLength); | _TimestampShift = (byte)(WorkerIdBitLength + SeqBitLength); | ||||
_CurrentSeqNumber = options.MinSeqNumber; | _CurrentSeqNumber = options.MinSeqNumber; | ||||
@@ -351,6 +351,7 @@ namespace Yitter.IdGenerator | |||||
while (tempTimeTicker <= _LastTimeTick) | while (tempTimeTicker <= _LastTimeTick) | ||||
{ | { | ||||
Thread.Sleep(1); | |||||
tempTimeTicker = GetCurrentTimeTick(); | tempTimeTicker = GetCurrentTimeTick(); | ||||
} | } | ||||
@@ -92,6 +92,12 @@ namespace Yitter.IdGenerator | |||||
throw new ApplicationException("MinSeqNumber error. (range:[5, " + maxSeqNumber + "]"); | throw new ApplicationException("MinSeqNumber error. (range:[5, " + maxSeqNumber + "]"); | ||||
} | } | ||||
// 7.TopOverCostCount | |||||
if (options.TopOverCostCount < 0 || options.TopOverCostCount > 10000) | |||||
{ | |||||
throw new ApplicationException("TopOverCostCount error. (range:[0, 10000]"); | |||||
} | |||||
switch (options.Method) | switch (options.Method) | ||||
{ | { | ||||
case 2: | case 2: | ||||
@@ -34,17 +34,24 @@ namespace Yitter.IdGenerator | |||||
/// <summary> | /// <summary> | ||||
/// 生成新的Id | /// 生成新的Id | ||||
/// 调用本方法前,请确保调用了 SetIdGenerator 方法做初始化。 | /// 调用本方法前,请确保调用了 SetIdGenerator 方法做初始化。 | ||||
/// 否则将会初始化一个WorkerId为1的对象。 | |||||
/// </summary> | /// </summary> | ||||
/// <returns></returns> | /// <returns></returns> | ||||
public static long NextId() | public static long NextId() | ||||
{ | { | ||||
if (_IdGenInstance == null) | |||||
{ | |||||
_IdGenInstance = new DefaultIdGenerator( | |||||
new IdGeneratorOptions() { WorkerId = 0 } | |||||
); | |||||
} | |||||
//if (_IdGenInstance == null) | |||||
//{ | |||||
// lock (_IdGenInstance) | |||||
// { | |||||
// if (_IdGenInstance == null) | |||||
// { | |||||
// _IdGenInstance = new DefaultIdGenerator( | |||||
// new IdGeneratorOptions() { WorkerId = 0 } | |||||
// ); | |||||
// } | |||||
// } | |||||
//} | |||||
if (_IdGenInstance == null) throw new ApplicationException("Please initialize Yitter.IdGeneratorOptions first."); | |||||
return _IdGenInstance.NewLong(); | return _IdGenInstance.NewLong(); | ||||
} | } | ||||
@@ -18,8 +18,10 @@ | |||||
<Copyright>Yitter</Copyright> | <Copyright>Yitter</Copyright> | ||||
<PackageProjectUrl>https://github.com/yitter/idgenerator</PackageProjectUrl> | <PackageProjectUrl>https://github.com/yitter/idgenerator</PackageProjectUrl> | ||||
<PackageLicenseExpression>MIT</PackageLicenseExpression> | <PackageLicenseExpression>MIT</PackageLicenseExpression> | ||||
<Version>1.0.12</Version> | |||||
<Version>1.0.14</Version> | |||||
<PackageReleaseNotes></PackageReleaseNotes> | <PackageReleaseNotes></PackageReleaseNotes> | ||||
<AssemblyVersion>1.0.0.*</AssemblyVersion> | |||||
<FileVersion>1.0.0.*</FileVersion> | |||||
</PropertyGroup> | </PropertyGroup> | ||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'"> | ||||
@@ -1,7 +1,7 @@ | |||||
## Ignore Visual Studio temporary files, build results, and | ## Ignore Visual Studio temporary files, build results, and | ||||
## files generated by popular Visual Studio add-ons. | ## files generated by popular Visual Studio add-ons. | ||||
build/* | |||||
build | |||||
# User-specific files | # User-specific files | ||||
*.suo | *.suo | ||||
@@ -29,6 +29,7 @@ bld/ | |||||
**/.vs/ | **/.vs/ | ||||
# Uncomment if you have tasks that create the project's static files in wwwroot | # Uncomment if you have tasks that create the project's static files in wwwroot | ||||
#wwwroot/ | #wwwroot/ | ||||
.vscode | |||||
# MSTest test Results | # MSTest test Results | ||||
[Tt]est[Rr]esult*/ | [Tt]est[Rr]esult*/ | ||||
@@ -254,7 +255,8 @@ paket-files/ | |||||
.idea/ | .idea/ | ||||
*.sln.iml | *.sln.iml | ||||
target/ | target/ | ||||
cmake-build*/ | |||||
cmake-build-* | |||||
source.code-* | |||||
# macOS | # macOS | ||||
.DS_Store | .DS_Store |
@@ -8,18 +8,17 @@ set(CMAKE_C_STANDARD 11) | |||||
aux_source_directory(. DIR_SRCS) | aux_source_directory(. DIR_SRCS) | ||||
add_subdirectory(idgen) | add_subdirectory(idgen) | ||||
#编译动态库 | #编译动态库 | ||||
#set(LIB_SRC YitIdHelper.h YitIdHelper.c) | |||||
#add_library(YitIdGenLib SHARED ${LIB_SRC}) | |||||
#target_link_libraries(YitIdGenLib idgen) | |||||
#set_target_properties(YitIdGenLib PROPERTIES | |||||
# LINKER_LANGUAGE C | |||||
# OUTPUT_NAME "yitidgenc" | |||||
# PREFIX "") | |||||
##编译执行文件 | |||||
set(LIB_SRC YitIdHelper.h YitIdHelper.c) | set(LIB_SRC YitIdHelper.h YitIdHelper.c) | ||||
add_library(YitIdGenLib SHARED ${LIB_SRC}) | |||||
target_link_libraries(YitIdGenLib idgen) | |||||
set_target_properties(YitIdGenLib PROPERTIES | |||||
LINKER_LANGUAGE C | |||||
OUTPUT_NAME "yitidgenc" | |||||
PREFIX "") | |||||
# 编译执行文件 | |||||
# set(LIB_SRC YitIdHelper.h YitIdHelper.c) | |||||
add_library(YitIdHelper ${LIB_SRC}) | add_library(YitIdHelper ${LIB_SRC}) | ||||
add_executable(YitIdGen main.c) | add_executable(YitIdGen main.c) | ||||
target_link_libraries(YitIdGen YitIdHelper pthread) | target_link_libraries(YitIdGen YitIdHelper pthread) | ||||
@@ -9,107 +9,147 @@ | |||||
#include <unistd.h> | #include <unistd.h> | ||||
#include "IdGenerator.h" | #include "IdGenerator.h" | ||||
static inline uint64_t WorkerM1Id() { | |||||
static inline uint64_t WorkerM1Id() | |||||
{ | |||||
return WorkerM1NextId(_idGenerator->Worker); | return WorkerM1NextId(_idGenerator->Worker); | ||||
} | } | ||||
static inline uint64_t WorkerM2Id() { | |||||
static inline uint64_t WorkerM2Id() | |||||
{ | |||||
return WorkerM2NextId(_idGenerator->Worker); | return WorkerM2NextId(_idGenerator->Worker); | ||||
} | } | ||||
extern IdGenerator *GetIdGenInstance() { | |||||
extern IdGenerator *GetIdGenInstance() | |||||
{ | |||||
if (_idGenerator != NULL) | if (_idGenerator != NULL) | ||||
return _idGenerator; | return _idGenerator; | ||||
else { | |||||
_idGenerator = (IdGenerator *) malloc(sizeof(IdGenerator)); | |||||
else | |||||
{ | |||||
_idGenerator = (IdGenerator *)malloc(sizeof(IdGenerator)); | |||||
_idGenerator->Worker = NewSnowFlakeWorker(); | _idGenerator->Worker = NewSnowFlakeWorker(); | ||||
return _idGenerator; | return _idGenerator; | ||||
} | } | ||||
} | } | ||||
extern void SetOptions(IdGeneratorOptions options) { | |||||
if (GetIdGenInstance() == NULL) { | |||||
extern void SetOptions(IdGeneratorOptions options) | |||||
{ | |||||
if (GetIdGenInstance() == NULL) | |||||
{ | |||||
exit(1); | exit(1); | ||||
} | } | ||||
// 1.BaseTime | // 1.BaseTime | ||||
if (options.BaseTime == 0) { | |||||
if (options.BaseTime == 0) | |||||
{ | |||||
_idGenerator->Worker->BaseTime = 1582136402000; | _idGenerator->Worker->BaseTime = 1582136402000; | ||||
} else if (options.BaseTime < 631123200000 || options.BaseTime > GetCurrentTime()) { | |||||
} | |||||
else if (options.BaseTime < 631123200000 || options.BaseTime > GetCurrentTime()) | |||||
{ | |||||
perror("BaseTime error."); | perror("BaseTime error."); | ||||
exit(1); | exit(1); | ||||
} else { | |||||
} | |||||
else | |||||
{ | |||||
_idGenerator->Worker->BaseTime = options.BaseTime; | _idGenerator->Worker->BaseTime = options.BaseTime; | ||||
} | } | ||||
// 2.WorkerIdBitLength | // 2.WorkerIdBitLength | ||||
if (options.WorkerIdBitLength <= 0) { | |||||
if (options.WorkerIdBitLength <= 0) | |||||
{ | |||||
perror("WorkerIdBitLength error.(range:[1, 21])"); | perror("WorkerIdBitLength error.(range:[1, 21])"); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
if (options.SeqBitLength + options.WorkerIdBitLength > 22) { | |||||
if (options.SeqBitLength + options.WorkerIdBitLength > 22) | |||||
{ | |||||
perror("error:WorkerIdBitLength + SeqBitLength <= 22"); | perror("error:WorkerIdBitLength + SeqBitLength <= 22"); | ||||
exit(1); | exit(1); | ||||
} else { | |||||
} | |||||
else | |||||
{ | |||||
// _idGenerator->Worker->WorkerIdBitLength = options.WorkerIdBitLength; | // _idGenerator->Worker->WorkerIdBitLength = options.WorkerIdBitLength; | ||||
_idGenerator->Worker->WorkerIdBitLength = options.WorkerIdBitLength <= 0 ? 6 : options.WorkerIdBitLength; | _idGenerator->Worker->WorkerIdBitLength = options.WorkerIdBitLength <= 0 ? 6 : options.WorkerIdBitLength; | ||||
} | } | ||||
// 3.WorkerId | // 3.WorkerId | ||||
uint32_t maxWorkerIdNumber = (1 << options.WorkerIdBitLength) - 1; | uint32_t maxWorkerIdNumber = (1 << options.WorkerIdBitLength) - 1; | ||||
if (maxWorkerIdNumber == 0) { | |||||
if (maxWorkerIdNumber == 0) | |||||
{ | |||||
maxWorkerIdNumber = 63; | maxWorkerIdNumber = 63; | ||||
} | } | ||||
if (options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber) { | |||||
if (options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber) | |||||
{ | |||||
perror("WorkerId error. (range:[0, {2^options.WorkerIdBitLength-1]}"); | perror("WorkerId error. (range:[0, {2^options.WorkerIdBitLength-1]}"); | ||||
exit(1); | exit(1); | ||||
} else { | |||||
} | |||||
else | |||||
{ | |||||
_idGenerator->Worker->WorkerId = options.WorkerId; | _idGenerator->Worker->WorkerId = options.WorkerId; | ||||
} | } | ||||
// 4.SeqBitLength | // 4.SeqBitLength | ||||
if (options.SeqBitLength < 2 || options.SeqBitLength > 21) { | |||||
if (options.SeqBitLength < 2 || options.SeqBitLength > 21) | |||||
{ | |||||
perror("SeqBitLength error. (range:[2, 21])"); | perror("SeqBitLength error. (range:[2, 21])"); | ||||
exit(1); | exit(1); | ||||
} else { | |||||
} | |||||
else | |||||
{ | |||||
// _idGenerator->Worker->SeqBitLength = options.SeqBitLength; | // _idGenerator->Worker->SeqBitLength = options.SeqBitLength; | ||||
_idGenerator->Worker->SeqBitLength = options.SeqBitLength <= 0 ? 6 : options.SeqBitLength; | _idGenerator->Worker->SeqBitLength = options.SeqBitLength <= 0 ? 6 : options.SeqBitLength; | ||||
} | } | ||||
// 5.MaxSeqNumber | // 5.MaxSeqNumber | ||||
uint32_t maxSeqNumber = (1 << options.SeqBitLength) - 1; | uint32_t maxSeqNumber = (1 << options.SeqBitLength) - 1; | ||||
if (maxSeqNumber == 0) { | |||||
if (maxSeqNumber == 0) | |||||
{ | |||||
maxSeqNumber = 63; | maxSeqNumber = 63; | ||||
} | } | ||||
if (options.MaxSeqNumber > maxSeqNumber) { | |||||
if (options.MaxSeqNumber > maxSeqNumber) | |||||
{ | |||||
perror("MaxSeqNumber error. (range:[1, {2^options.SeqBitLength-1}]"); | perror("MaxSeqNumber error. (range:[1, {2^options.SeqBitLength-1}]"); | ||||
exit(1); | exit(1); | ||||
} else { | |||||
} | |||||
else | |||||
{ | |||||
_idGenerator->Worker->MaxSeqNumber = options.MaxSeqNumber <= 0 ? maxSeqNumber : options.MaxSeqNumber; | _idGenerator->Worker->MaxSeqNumber = options.MaxSeqNumber <= 0 ? maxSeqNumber : options.MaxSeqNumber; | ||||
} | } | ||||
// 6.MinSeqNumber | // 6.MinSeqNumber | ||||
if (options.MinSeqNumber < 5 || options.MinSeqNumber > maxSeqNumber) { | |||||
if (options.MinSeqNumber < 5 || options.MinSeqNumber > maxSeqNumber) | |||||
{ | |||||
perror("MinSeqNumber error. (range:[5, {options.MinSeqNumber}]"); | perror("MinSeqNumber error. (range:[5, {options.MinSeqNumber}]"); | ||||
exit(1); | exit(1); | ||||
} else { | |||||
} | |||||
else | |||||
{ | |||||
_idGenerator->Worker->MinSeqNumber = options.MinSeqNumber <= 0 ? 5 : options.MinSeqNumber; | _idGenerator->Worker->MinSeqNumber = options.MinSeqNumber <= 0 ? 5 : options.MinSeqNumber; | ||||
} | } | ||||
// 7.Others | |||||
_idGenerator->Worker->TopOverCostCount = options.TopOverCostCount <= 0 ? 2000 : options.TopOverCostCount; | |||||
// 7.TopOverCostCount | |||||
if (options.TopOverCostCount < 0 || options.TopOverCostCount > 10000) | |||||
{ | |||||
perror("TopOverCostCount error. (range:[0, 10000]"); | |||||
exit(1); | |||||
} | |||||
else | |||||
{ | |||||
//_idGenerator->Worker->TopOverCostCount = options.TopOverCostCount <= 0 ? 2000 : options.TopOverCostCount; | |||||
_idGenerator->Worker->TopOverCostCount = options.TopOverCostCount; | |||||
} | |||||
// 8.Others | |||||
_idGenerator->Worker->_TimestampShift = | _idGenerator->Worker->_TimestampShift = | ||||
_idGenerator->Worker->WorkerIdBitLength + _idGenerator->Worker->SeqBitLength; | |||||
_idGenerator->Worker->WorkerIdBitLength + _idGenerator->Worker->SeqBitLength; | |||||
_idGenerator->Worker->_CurrentSeqNumber = _idGenerator->Worker->MinSeqNumber; | _idGenerator->Worker->_CurrentSeqNumber = _idGenerator->Worker->MinSeqNumber; | ||||
_idGenerator->Worker->Method = options.Method; | _idGenerator->Worker->Method = options.Method; | ||||
if (options.Method == 2) { | |||||
if (options.Method == 2) | |||||
{ | |||||
_idGenerator->NextId = WorkerM2Id; | _idGenerator->NextId = WorkerM2Id; | ||||
} else { | |||||
} | |||||
else | |||||
{ | |||||
_idGenerator->NextId = WorkerM1Id; | _idGenerator->NextId = WorkerM1Id; | ||||
sleep(1); | |||||
usleep(500 * 1000); // 暂停500ms | |||||
} | } | ||||
} | } | ||||
@@ -162,6 +162,7 @@ extern int64_t GetCurrentMicroTime() { | |||||
extern int64_t GetNextTimeTick(SnowFlakeWorker *worker) { | extern int64_t GetNextTimeTick(SnowFlakeWorker *worker) { | ||||
uint64_t tempTimeTicker = GetCurrentTimeTick(worker); | uint64_t tempTimeTicker = GetCurrentTimeTick(worker); | ||||
while (tempTimeTicker <= worker->_LastTimeTick) { | while (tempTimeTicker <= worker->_LastTimeTick) { | ||||
usleep(1000); // 暂停1ms | |||||
tempTimeTicker = GetCurrentTimeTick(worker); | tempTimeTicker = GetCurrentTimeTick(worker); | ||||
} | } | ||||
return tempTimeTicker; | return tempTimeTicker; | ||||
@@ -13,51 +13,62 @@ | |||||
#include "idgen/IdGenerator.h" | #include "idgen/IdGenerator.h" | ||||
#include "YitIdHelper.h" | #include "YitIdHelper.h" | ||||
const int GenIdCount = 50000; | |||||
const int GenIdCount = 500000; | |||||
const bool multiThread = false; | const bool multiThread = false; | ||||
const int threadCount = 50; | const int threadCount = 50; | ||||
const int method = 1; | const int method = 1; | ||||
void RunMultiThread() { | |||||
//int64_t start = GetCurrentMicroTime(); | |||||
for (int i = 0; i < GenIdCount / threadCount; i++) { | |||||
void RunMultiThread() | |||||
{ | |||||
// int64_t start = GetCurrentMicroTime(); | |||||
for (int i = 0; i < GenIdCount / threadCount; i++) | |||||
{ | |||||
int64_t id = NextId(); | int64_t id = NextId(); | ||||
printf("ID: %D\n", id); | printf("ID: %D\n", id); | ||||
} | } | ||||
int64_t end = GetCurrentMicroTime(); | int64_t end = GetCurrentMicroTime(); | ||||
//printf("%s,total:%d μs\n", method == 1 ? "1" : "2", (end - start)); | |||||
// printf("%s,total:%d μs\n", method == 1 ? "1" : "2", (end - start)); | |||||
} | } | ||||
void RunSingle() { | |||||
void RunSingle() | |||||
{ | |||||
int64_t start = GetCurrentMicroTime(); | int64_t start = GetCurrentMicroTime(); | ||||
for (int i = 0; i < GenIdCount; i++) { | |||||
for (int i = 0; i < GenIdCount; i++) | |||||
{ | |||||
int64_t id = NextId(); | int64_t id = NextId(); | ||||
// printf("ID: %ld\n", id); | |||||
// printf("ID: %ld\n", id); | |||||
} | } | ||||
int64_t end = GetCurrentMicroTime(); | int64_t end = GetCurrentMicroTime(); | ||||
printf("%s, total: %d us\n", method == 1 ? "1" : "2", (end - start)); | printf("%s, total: %d us\n", method == 1 ? "1" : "2", (end - start)); | ||||
} | } | ||||
int main() { | |||||
int main() | |||||
{ | |||||
IdGeneratorOptions options = BuildIdGenOptions(1); | IdGeneratorOptions options = BuildIdGenOptions(1); | ||||
options.Method = method; | options.Method = method; | ||||
options.WorkerId = 1; | options.WorkerId = 1; | ||||
options.SeqBitLength = 6; | |||||
options.SeqBitLength = 10; | |||||
// options.TopOverCostCount = 2000; | |||||
SetIdGenerator(options); | SetIdGenerator(options); | ||||
pthread_t tid[threadCount]; | pthread_t tid[threadCount]; | ||||
while (1) { | |||||
if (multiThread) { | |||||
for (int i = 0; i < threadCount; i++) { | |||||
if (pthread_create(&tid[i], NULL, (void *) RunMultiThread, NULL) != 0) { | |||||
while (1) | |||||
{ | |||||
if (multiThread) | |||||
{ | |||||
for (int i = 0; i < threadCount; i++) | |||||
{ | |||||
if (pthread_create(&tid[i], NULL, (void *)RunMultiThread, NULL) != 0) | |||||
{ | |||||
printf("thread creation failed\n"); | printf("thread creation failed\n"); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
} | } | ||||
} else { | |||||
} | |||||
else | |||||
{ | |||||
RunSingle(); | RunSingle(); | ||||
} | } | ||||
@@ -31,7 +31,7 @@ var newId = idgen.NextId() | |||||
## 关于Go环境 | ## 关于Go环境 | ||||
1.SDK,go1.14 | |||||
1.SDK,go1.16 | |||||
2.启用 Go-Modules | 2.启用 Go-Modules | ||||
``` | ``` | ||||
@@ -0,0 +1,262 @@ | |||||
## Ignore Visual Studio temporary files, build results, and | |||||
## files generated by popular Visual Studio add-ons. | |||||
# User-specific files | |||||
*.suo | |||||
*.user | |||||
*.userosscache | |||||
*.sln.docstates | |||||
*.editorconfig | |||||
.vscode | |||||
__commit.bat | |||||
__download.bat | |||||
target | |||||
# User-specific files (MonoDevelop/Xamarin Studio) | |||||
*.userprefs | |||||
# Build results | |||||
[Dd]ebug/ | |||||
[Dd]ebugPublic/ | |||||
[Rr]elease/ | |||||
[Rr]eleases/ | |||||
x64/ | |||||
x86/ | |||||
bld/ | |||||
[Bb]in/ | |||||
[Oo]bj/ | |||||
[Ll]og/ | |||||
# Visual Studio 2015 cache/options directory | |||||
**/.vs/ | |||||
# Uncomment if you have tasks that create the project's static files in wwwroot | |||||
#wwwroot/ | |||||
# MSTest test Results | |||||
[Tt]est[Rr]esult*/ | |||||
[Bb]uild[Ll]og.* | |||||
# NUNIT | |||||
*.VisualState.xml | |||||
TestResult.xml | |||||
# Build Results of an ATL Project | |||||
[Dd]ebugPS/ | |||||
[Rr]eleasePS/ | |||||
dlldata.c | |||||
# DNX | |||||
project.lock.json | |||||
artifacts/ | |||||
*_i.c | |||||
*_p.c | |||||
*_i.h | |||||
*.ilk | |||||
*.meta | |||||
*.obj | |||||
*.pch | |||||
*.pdb | |||||
*.pgc | |||||
*.pgd | |||||
*.rsp | |||||
*.sbr | |||||
*.tlb | |||||
*.tli | |||||
*.tlh | |||||
*.tmp | |||||
*.tmp_proj | |||||
*.log | |||||
*.vspscc | |||||
*.vssscc | |||||
.builds | |||||
*.pidb | |||||
*.svclog | |||||
*.scc | |||||
# Chutzpah Test files | |||||
_Chutzpah* | |||||
# Visual C++ cache files | |||||
ipch/ | |||||
*.aps | |||||
*.ncb | |||||
*.opendb | |||||
*.opensdf | |||||
*.sdf | |||||
*.cachefile | |||||
*.VC.db | |||||
*.VC.VC.opendb | |||||
# Visual Studio profiler | |||||
*.psess | |||||
*.vsp | |||||
*.vspx | |||||
*.sap | |||||
# TFS 2012 Local Workspace | |||||
$tf/ | |||||
# Guidance Automation Toolkit | |||||
*.gpState | |||||
# ReSharper is a .NET coding add-in | |||||
_ReSharper*/ | |||||
*.[Rr]e[Ss]harper | |||||
*.DotSettings.user | |||||
# JustCode is a .NET coding add-in | |||||
.JustCode | |||||
# TeamCity is a build add-in | |||||
_TeamCity* | |||||
# DotCover is a Code Coverage Tool | |||||
*.dotCover | |||||
# NCrunch | |||||
_NCrunch_* | |||||
.*crunch*.local.xml | |||||
nCrunchTemp_* | |||||
# MightyMoose | |||||
*.mm.* | |||||
AutoTest.Net/ | |||||
# Web workbench (sass) | |||||
.sass-cache/ | |||||
# Installshield output folder | |||||
[Ee]xpress/ | |||||
# DocProject is a documentation generator add-in | |||||
DocProject/buildhelp/ | |||||
DocProject/Help/*.HxT | |||||
DocProject/Help/*.HxC | |||||
DocProject/Help/*.hhc | |||||
DocProject/Help/*.hhk | |||||
DocProject/Help/*.hhp | |||||
DocProject/Help/Html2 | |||||
DocProject/Help/html | |||||
# Click-Once directory | |||||
publish/ | |||||
# Publish Web Output | |||||
*.[Pp]ublish.xml | |||||
*.azurePubxml | |||||
# TODO: Comment the next line if you want to checkin your web deploy settings | |||||
# but database connection strings (with potential passwords) will be unencrypted | |||||
*.pubxml | |||||
*.publishproj | |||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to | |||||
# checkin your Azure Web App publish settings, but sensitive information contained | |||||
# in these scripts will be unencrypted | |||||
PublishScripts/ | |||||
# NuGet Packages | |||||
*.nupkg | |||||
*.snupkg | |||||
# The packages folder can be ignored because of Package Restore | |||||
**/packages/* | |||||
# except build/, which is used as an MSBuild target. | |||||
!**/packages/build/ | |||||
# Uncomment if necessary however generally it will be regenerated when needed | |||||
#!**/packages/repositories.config | |||||
# NuGet v3's project.json files produces more ignoreable files | |||||
*.nuget.props | |||||
*.nuget.targets | |||||
# Microsoft Azure Build Output | |||||
csx/ | |||||
*.build.csdef | |||||
# Microsoft Azure Emulator | |||||
ecf/ | |||||
rcf/ | |||||
# Windows Store app package directories and files | |||||
AppPackages/ | |||||
BundleArtifacts/ | |||||
Package.StoreAssociation.xml | |||||
_pkginfo.txt | |||||
# Visual Studio cache files | |||||
# files ending in .cache can be ignored | |||||
*.[Cc]ache | |||||
# but keep track of directories ending in .cache | |||||
!*.[Cc]ache/ | |||||
# Others | |||||
ClientBin/ | |||||
~$* | |||||
*~ | |||||
*.dbmdl | |||||
*.dbproj.schemaview | |||||
*.pfx | |||||
*.publishsettings | |||||
node_modules/ | |||||
orleans.codegen.cs | |||||
# Since there are multiple workflows, uncomment next line to ignore bower_components | |||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) | |||||
#bower_components/ | |||||
# RIA/Silverlight projects | |||||
Generated_Code/ | |||||
# Backup & report files from converting an old project file | |||||
# to a newer Visual Studio version. Backup files are not needed, | |||||
# because we have git ;-) | |||||
_UpgradeReport_Files/ | |||||
Backup*/ | |||||
UpgradeLog*.XML | |||||
UpgradeLog*.htm | |||||
# SQL Server files | |||||
*.mdf | |||||
*.ldf | |||||
# Business Intelligence projects | |||||
*.rdl.data | |||||
*.bim.layout | |||||
*.bim_*.settings | |||||
# Microsoft Fakes | |||||
FakesAssemblies/ | |||||
# GhostDoc plugin setting file | |||||
*.GhostDoc.xml | |||||
# Node.js Tools for Visual Studio | |||||
.ntvs_analysis.dat | |||||
# Visual Studio 6 build log | |||||
*.plg | |||||
# Visual Studio 6 workspace options file | |||||
*.opt | |||||
# Visual Studio LightSwitch build output | |||||
**/*.HTMLClient/GeneratedArtifacts | |||||
**/*.DesktopClient/GeneratedArtifacts | |||||
**/*.DesktopClient/ModelManifest.xml | |||||
**/*.Server/GeneratedArtifacts | |||||
**/*.Server/ModelManifest.xml | |||||
_Pvt_Extensions | |||||
# Paket dependency manager | |||||
.paket/paket.exe | |||||
paket-files/ | |||||
# FAKE - F# Make | |||||
.fake/ | |||||
# JetBrains Rider | |||||
.idea/ | |||||
*.sln.iml | |||||
# macOS | |||||
.DS_Store |
@@ -0,0 +1,10 @@ | |||||
module github.com/yitter/idgenerator-go | |||||
go 1.17 | |||||
require github.com/go-redis/redis/v8 v8.11.5 | |||||
require ( | |||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect | |||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect | |||||
) |
@@ -0,0 +1,106 @@ | |||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= | |||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= | |||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= | |||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= | |||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= | |||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | |||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | |||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= | |||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= | |||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= | |||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= | |||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= | |||||
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= | |||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= | |||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= | |||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | |||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= | |||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= | |||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= | |||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= | |||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= | |||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= | |||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= | |||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= | |||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | |||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | |||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | |||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | |||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= | |||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= | |||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= | |||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= | |||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= | |||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= | |||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | |||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= | |||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= | |||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= | |||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= | |||||
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= | |||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= | |||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= | |||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= | |||||
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= | |||||
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= | |||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | |||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | |||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= | |||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | |||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | |||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | |||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | |||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= | |||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= | |||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= | |||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | |||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= | |||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | |||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0= | |||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= | |||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | |||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= | |||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= | |||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | |||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | |||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | |||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= | |||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | |||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | |||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | |||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | |||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | |||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= | |||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= | |||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= | |||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= | |||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= | |||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | |||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= | |||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= | |||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | |||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= | |||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= | |||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= | |||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= | |||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= |
@@ -0,0 +1,69 @@ | |||||
package main | |||||
import ( | |||||
"C" | |||||
"fmt" | |||||
"time" | |||||
"github.com/yitter/idgenerator-go/regworkerid" | |||||
) | |||||
func main() { | |||||
ip := "localhost" | |||||
password := "" | |||||
ipChar := C.CString(ip) | |||||
passChar := C.CString(password) | |||||
workerIdList := RegisterMany(ipChar, 6379, passChar, 4, 3, 0) | |||||
for _, value := range workerIdList { | |||||
fmt.Println("注册的WorkerId:", value) | |||||
} | |||||
id := RegisterOne(ipChar, 6379, passChar, 4, 0) | |||||
fmt.Println("注册的WorkerId:", id) | |||||
// var workerId = regworkerid.RegisterOne(ip, 6379, "", 4) | |||||
// fmt.Println("注册的WorkerId:", workerId) | |||||
fmt.Println("end") | |||||
time.Sleep(time.Duration(300) * time.Second) | |||||
} | |||||
//export RegisterOne | |||||
// 注册一个 WorkerId | |||||
func RegisterOne(ip *C.char, port int32, password *C.char, maxWorkerId int32, database int) int32 { | |||||
return regworkerid.RegisterOne(C.GoString(ip), port, C.GoString(password), maxWorkerId, database) | |||||
} | |||||
//export UnRegister | |||||
// 注销本机已注册的 WorkerId | |||||
func UnRegister() { | |||||
regworkerid.UnRegister() | |||||
} | |||||
// export Validate | |||||
// 检查本地WorkerId是否有效(0-有效,其它-无效) | |||||
func Validate(workerId int32) int32 { | |||||
return regworkerid.Validate(workerId) | |||||
} | |||||
// RegisterMany | |||||
// 注册多个 WorkerId,会先注销所有本机已注册的记录 | |||||
func RegisterMany(ip *C.char, port int32, password *C.char, maxWorkerId, totalCount int32, database int) []int32 { | |||||
// return (*C.int)(unsafe.Pointer(&values)) | |||||
//return regworkerid.RegisterMany(ip, port, password, maxWorkerId, totalCount, database) | |||||
return regworkerid.RegisterMany(C.GoString(ip), port, C.GoString(password), maxWorkerId, totalCount, database) | |||||
} | |||||
// To Build a dll/so: | |||||
// windows: | |||||
// go build -o ./target/yitidgengo.dll -buildmode=c-shared main.go | |||||
// // go build -o ./target/yitidgengo.dll -buildmode=c-shared main.go reg.go | |||||
// linux init: go install -buildmode=shared -linkshared std | |||||
// go build -o ./target/yitidgengo.so -buildmode=c-shared main.go | |||||
// go build -o ./target/yitidgengo.so -buildmode=c-shared main.go reg.go | |||||
// https://books.studygolang.com/advanced-go-programming-book/ch2-cgo/ch2-09-static-shared-lib.html |
@@ -0,0 +1,5 @@ | |||||
package main | |||||
import ( | |||||
"C" | |||||
) |
@@ -0,0 +1,262 @@ | |||||
## Ignore Visual Studio temporary files, build results, and | |||||
## files generated by popular Visual Studio add-ons. | |||||
# User-specific files | |||||
*.suo | |||||
*.user | |||||
*.userosscache | |||||
*.sln.docstates | |||||
*.editorconfig | |||||
.vscode | |||||
__commit.bat | |||||
__download.bat | |||||
target | |||||
# User-specific files (MonoDevelop/Xamarin Studio) | |||||
*.userprefs | |||||
# Build results | |||||
[Dd]ebug/ | |||||
[Dd]ebugPublic/ | |||||
[Rr]elease/ | |||||
[Rr]eleases/ | |||||
x64/ | |||||
x86/ | |||||
bld/ | |||||
[Bb]in/ | |||||
[Oo]bj/ | |||||
[Ll]og/ | |||||
# Visual Studio 2015 cache/options directory | |||||
**/.vs/ | |||||
# Uncomment if you have tasks that create the project's static files in wwwroot | |||||
#wwwroot/ | |||||
# MSTest test Results | |||||
[Tt]est[Rr]esult*/ | |||||
[Bb]uild[Ll]og.* | |||||
# NUNIT | |||||
*.VisualState.xml | |||||
TestResult.xml | |||||
# Build Results of an ATL Project | |||||
[Dd]ebugPS/ | |||||
[Rr]eleasePS/ | |||||
dlldata.c | |||||
# DNX | |||||
project.lock.json | |||||
artifacts/ | |||||
*_i.c | |||||
*_p.c | |||||
*_i.h | |||||
*.ilk | |||||
*.meta | |||||
*.obj | |||||
*.pch | |||||
*.pdb | |||||
*.pgc | |||||
*.pgd | |||||
*.rsp | |||||
*.sbr | |||||
*.tlb | |||||
*.tli | |||||
*.tlh | |||||
*.tmp | |||||
*.tmp_proj | |||||
*.log | |||||
*.vspscc | |||||
*.vssscc | |||||
.builds | |||||
*.pidb | |||||
*.svclog | |||||
*.scc | |||||
# Chutzpah Test files | |||||
_Chutzpah* | |||||
# Visual C++ cache files | |||||
ipch/ | |||||
*.aps | |||||
*.ncb | |||||
*.opendb | |||||
*.opensdf | |||||
*.sdf | |||||
*.cachefile | |||||
*.VC.db | |||||
*.VC.VC.opendb | |||||
# Visual Studio profiler | |||||
*.psess | |||||
*.vsp | |||||
*.vspx | |||||
*.sap | |||||
# TFS 2012 Local Workspace | |||||
$tf/ | |||||
# Guidance Automation Toolkit | |||||
*.gpState | |||||
# ReSharper is a .NET coding add-in | |||||
_ReSharper*/ | |||||
*.[Rr]e[Ss]harper | |||||
*.DotSettings.user | |||||
# JustCode is a .NET coding add-in | |||||
.JustCode | |||||
# TeamCity is a build add-in | |||||
_TeamCity* | |||||
# DotCover is a Code Coverage Tool | |||||
*.dotCover | |||||
# NCrunch | |||||
_NCrunch_* | |||||
.*crunch*.local.xml | |||||
nCrunchTemp_* | |||||
# MightyMoose | |||||
*.mm.* | |||||
AutoTest.Net/ | |||||
# Web workbench (sass) | |||||
.sass-cache/ | |||||
# Installshield output folder | |||||
[Ee]xpress/ | |||||
# DocProject is a documentation generator add-in | |||||
DocProject/buildhelp/ | |||||
DocProject/Help/*.HxT | |||||
DocProject/Help/*.HxC | |||||
DocProject/Help/*.hhc | |||||
DocProject/Help/*.hhk | |||||
DocProject/Help/*.hhp | |||||
DocProject/Help/Html2 | |||||
DocProject/Help/html | |||||
# Click-Once directory | |||||
publish/ | |||||
# Publish Web Output | |||||
*.[Pp]ublish.xml | |||||
*.azurePubxml | |||||
# TODO: Comment the next line if you want to checkin your web deploy settings | |||||
# but database connection strings (with potential passwords) will be unencrypted | |||||
*.pubxml | |||||
*.publishproj | |||||
# Microsoft Azure Web App publish settings. Comment the next line if you want to | |||||
# checkin your Azure Web App publish settings, but sensitive information contained | |||||
# in these scripts will be unencrypted | |||||
PublishScripts/ | |||||
# NuGet Packages | |||||
*.nupkg | |||||
*.snupkg | |||||
# The packages folder can be ignored because of Package Restore | |||||
**/packages/* | |||||
# except build/, which is used as an MSBuild target. | |||||
!**/packages/build/ | |||||
# Uncomment if necessary however generally it will be regenerated when needed | |||||
#!**/packages/repositories.config | |||||
# NuGet v3's project.json files produces more ignoreable files | |||||
*.nuget.props | |||||
*.nuget.targets | |||||
# Microsoft Azure Build Output | |||||
csx/ | |||||
*.build.csdef | |||||
# Microsoft Azure Emulator | |||||
ecf/ | |||||
rcf/ | |||||
# Windows Store app package directories and files | |||||
AppPackages/ | |||||
BundleArtifacts/ | |||||
Package.StoreAssociation.xml | |||||
_pkginfo.txt | |||||
# Visual Studio cache files | |||||
# files ending in .cache can be ignored | |||||
*.[Cc]ache | |||||
# but keep track of directories ending in .cache | |||||
!*.[Cc]ache/ | |||||
# Others | |||||
ClientBin/ | |||||
~$* | |||||
*~ | |||||
*.dbmdl | |||||
*.dbproj.schemaview | |||||
*.pfx | |||||
*.publishsettings | |||||
node_modules/ | |||||
orleans.codegen.cs | |||||
# Since there are multiple workflows, uncomment next line to ignore bower_components | |||||
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) | |||||
#bower_components/ | |||||
# RIA/Silverlight projects | |||||
Generated_Code/ | |||||
# Backup & report files from converting an old project file | |||||
# to a newer Visual Studio version. Backup files are not needed, | |||||
# because we have git ;-) | |||||
_UpgradeReport_Files/ | |||||
Backup*/ | |||||
UpgradeLog*.XML | |||||
UpgradeLog*.htm | |||||
# SQL Server files | |||||
*.mdf | |||||
*.ldf | |||||
# Business Intelligence projects | |||||
*.rdl.data | |||||
*.bim.layout | |||||
*.bim_*.settings | |||||
# Microsoft Fakes | |||||
FakesAssemblies/ | |||||
# GhostDoc plugin setting file | |||||
*.GhostDoc.xml | |||||
# Node.js Tools for Visual Studio | |||||
.ntvs_analysis.dat | |||||
# Visual Studio 6 build log | |||||
*.plg | |||||
# Visual Studio 6 workspace options file | |||||
*.opt | |||||
# Visual Studio LightSwitch build output | |||||
**/*.HTMLClient/GeneratedArtifacts | |||||
**/*.DesktopClient/GeneratedArtifacts | |||||
**/*.DesktopClient/ModelManifest.xml | |||||
**/*.Server/GeneratedArtifacts | |||||
**/*.Server/ModelManifest.xml | |||||
_Pvt_Extensions | |||||
# Paket dependency manager | |||||
.paket/paket.exe | |||||
paket-files/ | |||||
# FAKE - F# Make | |||||
.fake/ | |||||
# JetBrains Rider | |||||
.idea/ | |||||
*.sln.iml | |||||
# macOS | |||||
.DS_Store |
@@ -1,5 +1,8 @@ | |||||
module yitidgen | |||||
go 1.16 | |||||
require github.com/go-redis/redis/v8 v8.8.0 // indirect | |||||
module github.com/yitter/idgenerator-go | |||||
go 1.17 | |||||
require ( | |||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect | |||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect | |||||
) |
@@ -1,15 +1,18 @@ | |||||
github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= | |||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= | |||||
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE= | |||||
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= | |||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= | |||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= | |||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= | |||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | |||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= | ||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= | github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= | ||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= | github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= | ||||
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= | github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= | ||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= | github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= | ||||
github.com/go-redis/redis v6.15.9+incompatible h1:K0pv1D7EQUjfyoMql+r/jZqCLizCGKFlFgcHWWmHQjg= | |||||
github.com/go-redis/redis v6.15.9+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= | |||||
github.com/go-redis/redis/v8 v8.8.0 h1:fDZP58UN/1RD3DjtTXP/fFZ04TFohSYhjZDkcDe2dnw= | |||||
github.com/go-redis/redis/v8 v8.8.0/go.mod h1:F7resOH5Kdug49Otu24RjHWwgK7u9AmtqWMnCV1iP5Y= | |||||
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI= | |||||
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo= | |||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= | |||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= | ||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= | github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= | ||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= | github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= | ||||
@@ -17,38 +20,33 @@ github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrU | |||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= | github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= | ||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= | github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= | ||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= | github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= | ||||
github.com/golang/protobuf v1.4.3 h1:JjCZWpVbqXDqFVmTfYWEVTMIYrL/NPdPSCHPJ0T/raM= | |||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= | |||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= | |||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= | |||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | ||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= | ||||
github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= | |||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= | ||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= | |||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= | github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= | ||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc= | |||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= | github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= | ||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= | github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= | ||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= | github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= | ||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= | ||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= | github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= | ||||
github.com/onsi/ginkgo v1.15.0/go.mod h1:hF8qUzuuC8DJGygJH3726JnCZX4MYbRB8yFfISqnKUg= | |||||
github.com/onsi/ginkgo v1.15.2 h1:l77YT15o814C2qVL47NOyjV/6RbaP7kKdrvZnxQ3Org= | |||||
github.com/onsi/ginkgo v1.15.2/go.mod h1:Dd6YFfwBW84ETqqtL0CPyPXillHgY6XhQH3uuCCTr/o= | |||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0= | |||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= | |||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= | |||||
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c= | |||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= | github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= | ||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= | github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= | ||||
github.com/onsi/gomega v1.10.5/go.mod h1:gza4q3jKQJijlu05nKWRCW/GavJumGt8aNRxWg7mt48= | |||||
github.com/onsi/gomega v1.11.0 h1:+CqWgvj0OZycCaqclBD1pxKHAU+tOkHmQIWvDHq2aug= | |||||
github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg= | |||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY= | |||||
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE= | |||||
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs= | |||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= | ||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= | |||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= | |||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= | ||||
go.opentelemetry.io/otel v0.19.0 h1:Lenfy7QHRXPZVsw/12CWpxX6d/JkrX8wrx2vO8G80Ng= | |||||
go.opentelemetry.io/otel v0.19.0/go.mod h1:j9bF567N9EfomkSidSfmMwIwIBuP37AMAIzVW85OxSg= | |||||
go.opentelemetry.io/otel/metric v0.19.0 h1:dtZ1Ju44gkJkYvo+3qGqVXmf88tc+a42edOywypengg= | |||||
go.opentelemetry.io/otel/metric v0.19.0/go.mod h1:8f9fglJPRnXuskQmKpnad31lcLJ2VmNNqIsx/uIwBSc= | |||||
go.opentelemetry.io/otel/oteltest v0.19.0/go.mod h1:tI4yxwh8U21v7JD6R3BcA/2+RBoTKFexE/PJ/nSO7IA= | |||||
go.opentelemetry.io/otel/trace v0.19.0 h1:1ucYlenXIDA1OlHVLDZKX0ObXV5RLaq06DtUKz5e5zc= | |||||
go.opentelemetry.io/otel/trace v0.19.0/go.mod h1:4IXiNextNOpPnRlI4ryK69mn5iC84bjBWZQA5DXz/qg= | |||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= | ||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= | ||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= | ||||
@@ -58,8 +56,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn | |||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= | ||||
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= | golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A= | ||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | ||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb h1:eBmm0M9fYhWpKZLjQUUKka/LtIxf46G4fxeEz5KJr9U= | |||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= | |||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0= | |||||
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= | |||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= | ||||
@@ -69,35 +67,40 @@ golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7w | |||||
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091 h1:DMyOG0U+gKfu8JZzg2UQe9MeaC1X+xQWlAKcRnjxjCw= | |||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | ||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= | |||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= | |||||
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= | |||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= | |||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= | ||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k= | |||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | ||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= | |||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= | |||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= | ||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= | ||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= | ||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= | |||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= | ||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= | google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= | ||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= | google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= | ||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= | google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= | ||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= | google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= | ||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= | google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= | ||||
google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= | |||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= | ||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | |||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= | |||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= | |||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= | gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= | ||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= | ||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= | ||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | |||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= | ||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= | gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= | ||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= | gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= | ||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
@@ -4,6 +4,7 @@ | |||||
* 代码修订:yitter | * 代码修订:yitter | ||||
* 开源地址:https://github.com/yitter/idgenerator | * 开源地址:https://github.com/yitter/idgenerator | ||||
*/ | */ | ||||
package idgen | package idgen | ||||
import ( | import ( | ||||
@@ -64,6 +65,11 @@ func NewDefaultIdGenerator(options *IdGeneratorOptions) *DefaultIdGenerator { | |||||
panic("MinSeqNumber error. (range:[5, " + strconv.FormatUint(uint64(maxSeqNumber), 10) + "]") | panic("MinSeqNumber error. (range:[5, " + strconv.FormatUint(uint64(maxSeqNumber), 10) + "]") | ||||
} | } | ||||
// 7.TopOverCostCount | |||||
if options.TopOverCostCount < 0 || options.TopOverCostCount > 10000 { | |||||
panic("TopOverCostCount error. (range:[0, 10000]") | |||||
} | |||||
var snowWorker ISnowWorker | var snowWorker ISnowWorker | ||||
switch options.Method { | switch options.Method { | ||||
case 1: | case 1: | ||||
@@ -87,3 +93,7 @@ func NewDefaultIdGenerator(options *IdGeneratorOptions) *DefaultIdGenerator { | |||||
func (dig DefaultIdGenerator) NewLong() int64 { | func (dig DefaultIdGenerator) NewLong() int64 { | ||||
return dig.SnowWorker.NextId() | return dig.SnowWorker.NextId() | ||||
} | } | ||||
func (dig DefaultIdGenerator) ExtractTime(id int64) time.Time { | |||||
return time.UnixMilli(id>>(dig.Options.WorkerIdBitLength+dig.Options.SeqBitLength) + dig.Options.BaseTime) | |||||
} |
@@ -4,6 +4,7 @@ | |||||
* 代码修订:yitter | * 代码修订:yitter | ||||
* 开源地址:https://github.com/yitter/idgenerator | * 开源地址:https://github.com/yitter/idgenerator | ||||
*/ | */ | ||||
package idgen | package idgen | ||||
import ( | import ( | ||||
@@ -13,13 +14,13 @@ import ( | |||||
// SnowWorkerM1 . | // SnowWorkerM1 . | ||||
type SnowWorkerM1 struct { | type SnowWorkerM1 struct { | ||||
BaseTime int64 //基础时间 | |||||
WorkerId uint16 //机器码 | |||||
WorkerIdBitLength byte //机器码位长 | |||||
SeqBitLength byte //自增序列数位长 | |||||
MaxSeqNumber uint32 //最大序列数(含) | |||||
MinSeqNumber uint32 //最小序列数(含) | |||||
TopOverCostCount uint32 //最大漂移次数 | |||||
BaseTime int64 // 基础时间 | |||||
WorkerId uint16 // 机器码 | |||||
WorkerIdBitLength byte // 机器码位长 | |||||
SeqBitLength byte // 自增序列数位长 | |||||
MaxSeqNumber uint32 // 最大序列数(含) | |||||
MinSeqNumber uint32 // 最小序列数(含) | |||||
TopOverCostCount uint32 // 最大漂移次数 | |||||
_TimestampShift byte | _TimestampShift byte | ||||
_CurrentSeqNumber uint32 | _CurrentSeqNumber uint32 | ||||
@@ -75,12 +76,13 @@ func NewSnowWorkerM1(options *IdGeneratorOptions) ISnowWorker { | |||||
// 6.MinSeqNumber | // 6.MinSeqNumber | ||||
var minSeqNumber = options.MinSeqNumber | var minSeqNumber = options.MinSeqNumber | ||||
// 7.Others | |||||
// 7.TopOverCostCount | |||||
var topOverCostCount = options.TopOverCostCount | var topOverCostCount = options.TopOverCostCount | ||||
if topOverCostCount == 0 { | |||||
topOverCostCount = 2000 | |||||
} | |||||
// if topOverCostCount == 0 { | |||||
// topOverCostCount = 2000 | |||||
// } | |||||
// 8.Others | |||||
timestampShift := (byte)(workerIdBitLength + seqBitLength) | timestampShift := (byte)(workerIdBitLength + seqBitLength) | ||||
currentSeqNumber := minSeqNumber | currentSeqNumber := minSeqNumber | ||||
@@ -232,6 +234,7 @@ func (m1 *SnowWorkerM1) GetCurrentTimeTick() int64 { | |||||
func (m1 *SnowWorkerM1) GetNextTimeTick() int64 { | func (m1 *SnowWorkerM1) GetNextTimeTick() int64 { | ||||
tempTimeTicker := m1.GetCurrentTimeTick() | tempTimeTicker := m1.GetCurrentTimeTick() | ||||
for tempTimeTicker <= m1._LastTimeTick { | for tempTimeTicker <= m1._LastTimeTick { | ||||
time.Sleep(time.Duration(1) * time.Millisecond) | |||||
tempTimeTicker = m1.GetCurrentTimeTick() | tempTimeTicker = m1.GetCurrentTimeTick() | ||||
} | } | ||||
return tempTimeTicker | return tempTimeTicker | ||||
@@ -1,7 +1,15 @@ | |||||
/* | |||||
* 版权属于:yitter(yitter@126.com) | |||||
* 代码编辑:guoyahao | |||||
* 代码修订:yitter | |||||
* 开源地址:https://github.com/yitter/idgenerator | |||||
*/ | |||||
package idgen | package idgen | ||||
import ( | import ( | ||||
"sync" | "sync" | ||||
"time" | |||||
) | ) | ||||
var singletonMutex sync.Mutex | var singletonMutex sync.Mutex | ||||
@@ -16,14 +24,20 @@ func SetIdGenerator(options *IdGeneratorOptions) { | |||||
// NextId . | // NextId . | ||||
func NextId() int64 { | func NextId() int64 { | ||||
//if idGenerator == nil { | |||||
// singletonMutex.Lock() | |||||
// defer singletonMutex.Unlock() | |||||
// if idGenerator == nil { | |||||
// options := NewIdGeneratorOptions(1) | |||||
// idGenerator = NewDefaultIdGenerator(options) | |||||
// } | |||||
//} | |||||
if idGenerator == nil { | if idGenerator == nil { | ||||
singletonMutex.Lock() | |||||
defer singletonMutex.Unlock() | |||||
if idGenerator == nil { | |||||
options := NewIdGeneratorOptions(1) | |||||
idGenerator = NewDefaultIdGenerator(options) | |||||
} | |||||
panic("Please initialize Yitter.IdGeneratorOptions first.") | |||||
} | } | ||||
return idGenerator.NewLong() | return idGenerator.NewLong() | ||||
} | } | ||||
func ExtractTime(id int64) time.Time { | |||||
return idGenerator.ExtractTime(id) | |||||
} |
@@ -1,136 +1,52 @@ | |||||
package main | package main | ||||
import ( | import ( | ||||
"C" | |||||
"fmt" | "fmt" | ||||
"time" | "time" | ||||
"yitidgen/idgen" | |||||
"yitidgen/regworkerid" | |||||
"github.com/yitter/idgenerator-go/idgen" | |||||
) | ) | ||||
//export SetOptions | |||||
func SetOptions(workerId uint16) { | func SetOptions(workerId uint16) { | ||||
var options = idgen.NewIdGeneratorOptions(workerId) | var options = idgen.NewIdGeneratorOptions(workerId) | ||||
idgen.SetIdGenerator(options) | idgen.SetIdGenerator(options) | ||||
} | } | ||||
//export NextId | |||||
func NextId() int64 { | func NextId() int64 { | ||||
return idgen.NextId() | return idgen.NextId() | ||||
} | } | ||||
// RegisterOne 注册一个 WorkerId,会先注销所有本机已注册的记录 | |||||
// address: Redis连接地址,单机模式示例:127.0.0.1:6379,哨兵/集群模式示例:127.0.0.1:26380,127.0.0.1:26381,127.0.0.1:26382 | |||||
// password: Redis连接密码 | |||||
// db: Redis指定存储库,示例:1 | |||||
// sentinelMasterName: Redis 哨兵模式下的服务名称,示例:mymaster | |||||
// maxWorkerId: WorkerId 最大值,示例:63 | |||||
//export RegisterOne | |||||
func RegisterOne(address *C.char, password *C.char, db int, sentinelMasterName *C.char, maxWorkerId int32) int32 { | |||||
return regworkerid.RegisterOne(regworkerid.RegisterConf{ | |||||
Address: C.GoString(address), | |||||
Password: C.GoString(password), | |||||
DB: db, | |||||
MasterName: C.GoString(sentinelMasterName), | |||||
MaxWorkerId: maxWorkerId, | |||||
}) | |||||
} | |||||
// RegisterMany 注册多个 WorkerId,会先注销所有本机已注册的记录 | |||||
// address: Redis连接地址,单机模式示例:127.0.0.1:6379,哨兵/集群模式示例:127.0.0.1:26380,127.0.0.1:26381,127.0.0.1:26382 | |||||
// password: Redis连接密码 | |||||
// db: Redis指定存储库,示例:1 | |||||
// sentinelMasterName: Redis 哨兵模式下的服务名称,示例:mymaster | |||||
// maxWorkerId: WorkerId 最大值,示例:63 | |||||
// totalCount: 获取N个WorkerId,示例:5 | |||||
//export RegisterMany | |||||
func RegisterMany(address *C.char, password *C.char, db int, sentinelMasterName *C.char, maxWorkerId int32, totalCount int32) []int32 { | |||||
return regworkerid.RegisterMany(regworkerid.RegisterConf{ | |||||
Address: C.GoString(address), | |||||
Password: C.GoString(password), | |||||
DB: db, | |||||
MasterName: C.GoString(sentinelMasterName), | |||||
MaxWorkerId: maxWorkerId, | |||||
TotalCount: totalCount, | |||||
}) | |||||
} | |||||
// UnRegister 注销本机已注册的 WorkerId | |||||
//export UnRegister | |||||
func UnRegister() { | |||||
regworkerid.UnRegister() | |||||
} | |||||
// Validate 检查本地WorkerId是否有效(0-有效,其它-无效) | |||||
//export Validate | |||||
func Validate(workerId int32) int32 { | |||||
return regworkerid.Validate(workerId) | |||||
} | |||||
func main() { | func main() { | ||||
const testGenId = true // 测试设置 | |||||
if testGenId { | |||||
// 自定义参数 | |||||
var options = idgen.NewIdGeneratorOptions(1) | |||||
options.WorkerIdBitLength = 6 | |||||
options.SeqBitLength = 6 | |||||
options.BaseTime = time.Date(2020, 2, 20, 2, 20, 2, 20, time.UTC).UnixNano() / 1e6 | |||||
idgen.SetIdGenerator(options) | |||||
// 自定义参数 | |||||
var options = idgen.NewIdGeneratorOptions(1) | |||||
options.WorkerIdBitLength = 6 | |||||
options.SeqBitLength = 10 | |||||
options.BaseTime = time.Date(2020, 2, 20, 2, 20, 2, 20, time.UTC).UnixNano() / 1e6 | |||||
idgen.SetIdGenerator(options) | |||||
var genCount = 50000 | |||||
var genCount = 500000 | |||||
for j := 0; j < 100000; j++ { | |||||
for { | for { | ||||
var begin = time.Now().UnixNano() / 1e3 | |||||
var begin = time.Now().UnixNano() / 1e6 | |||||
for i := 0; i < genCount; i++ { | for i := 0; i < genCount; i++ { | ||||
// 生成ID | // 生成ID | ||||
id := idgen.NextId() | |||||
fmt.Println(id) | |||||
idgen.NextId() | |||||
// fmt.Println(id) | |||||
} | } | ||||
var end = time.Now().UnixNano() / 1e3 | |||||
var end = time.Now().UnixNano() / 1e6 | |||||
fmt.Println(end - begin) | |||||
fmt.Println("耗时:", (end - begin), "ms") | |||||
time.Sleep(time.Duration(1000) * time.Millisecond) | time.Sleep(time.Duration(1000) * time.Millisecond) | ||||
} | } | ||||
} else { | |||||
//// Redis单机模式下,获取多个WorkerId | |||||
//workerIdList := regworkerid.RegisterMany(regworkerid.RegisterConf{ | |||||
// Address: "127.0.0.1:6379", | |||||
// Password: "", | |||||
// DB: 0, | |||||
// MaxWorkerId: 4, | |||||
// TotalCount: 3, | |||||
//}) | |||||
//for _, value := range workerIdList { | |||||
// fmt.Println("RegisterMany--注册的WorkerId:", value) | |||||
//} | |||||
// Redis单机模式下,获取一个WorkerId | |||||
var workerId = regworkerid.RegisterOne(regworkerid.RegisterConf{ | |||||
Address: "127.0.0.1:6379", | |||||
Password: "", | |||||
DB: 0, | |||||
MaxWorkerId: 4, | |||||
}) | |||||
fmt.Println("RegisterOne--注册的WorkerId:", workerId) | |||||
//// Redis哨兵模式下,获取一个WorkerId | |||||
//var workerId = regworkerid.RegisterOne(regworkerid.RegisterConf{ | |||||
// //Address: "127.0.0.1:26380,127.0.0.1:26381,127.0.0.1:26382", | |||||
// Password: "", | |||||
// DB: 0, | |||||
// MasterName: "mymaster", // 哨兵模式下的服务名称 | |||||
// MaxWorkerId: 4, | |||||
//}) | |||||
//fmt.Println("RegisterOne--注册的WorkerId:", workerId) | |||||
fmt.Println("end") | |||||
time.Sleep(time.Duration(300) * time.Second) | |||||
} | } | ||||
} | } | ||||
// To Build a dll/so: | |||||
// windows: | // windows: | ||||
// go build -o ./target/yitidgengo.dll -buildmode=c-shared main.go | // go build -o ./target/yitidgengo.dll -buildmode=c-shared main.go | ||||
// linux init: go install -buildmode=shared -linkshared std | // linux init: go install -buildmode=shared -linkshared std | ||||
// go build -o ./target/yitidgengo.so -buildmode=c-shared main.go | // go build -o ./target/yitidgengo.so -buildmode=c-shared main.go | ||||
// https://books.studygolang.com/advanced-go-programming-book/ch2-cgo/ch2-09-static-shared-lib.html |
@@ -19,7 +19,9 @@ | |||||
*.zip | *.zip | ||||
*.tar.gz | *.tar.gz | ||||
*.rar | *.rar | ||||
target/ | |||||
target | |||||
.vscode | |||||
*.code-workspace | |||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml | ||||
hs_err_pid* | hs_err_pid* |
@@ -41,9 +41,9 @@ | |||||
<properties> | <properties> | ||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> | ||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> | ||||
<maven.compiler.source>1.8</maven.compiler.source> | |||||
<maven.compiler.target>1.8</maven.compiler.target> | |||||
<java.version>1.8</java.version> | |||||
<maven.compiler.source>11</maven.compiler.source> | |||||
<maven.compiler.target>11</maven.compiler.target> | |||||
<java.version>11</java.version> | |||||
</properties> | </properties> | ||||
<dependencies> | <dependencies> | ||||
<dependency> | <dependency> | ||||
@@ -66,7 +66,8 @@ public class SnowWorkerM1 implements ISnowWorker { | |||||
SeqBitLength = options.SeqBitLength == 0 ? 6 : options.SeqBitLength; | SeqBitLength = options.SeqBitLength == 0 ? 6 : options.SeqBitLength; | ||||
MaxSeqNumber = options.MaxSeqNumber <= 0 ? (1 << SeqBitLength) - 1 : options.MaxSeqNumber; | MaxSeqNumber = options.MaxSeqNumber <= 0 ? (1 << SeqBitLength) - 1 : options.MaxSeqNumber; | ||||
MinSeqNumber = options.MinSeqNumber; | MinSeqNumber = options.MinSeqNumber; | ||||
TopOverCostCount = options.TopOverCostCount == 0 ? 2000 : options.TopOverCostCount; | |||||
// TopOverCostCount = options.TopOverCostCount == 0 ? 2000 : options.TopOverCostCount; | |||||
TopOverCostCount = options.TopOverCostCount; | |||||
_TimestampShift = (byte) (WorkerIdBitLength + SeqBitLength); | _TimestampShift = (byte) (WorkerIdBitLength + SeqBitLength); | ||||
_CurrentSeqNumber = MinSeqNumber; | _CurrentSeqNumber = MinSeqNumber; | ||||
} | } | ||||
@@ -150,11 +151,11 @@ public class SnowWorkerM1 implements ISnowWorker { | |||||
BeginTurnBackAction(_TurnBackTimeTick); | BeginTurnBackAction(_TurnBackTimeTick); | ||||
} | } | ||||
// try { | |||||
// Thread.sleep(1); | |||||
// } catch (InterruptedException e) { | |||||
// e.printStackTrace(); | |||||
// } | |||||
// try { | |||||
// Thread.sleep(1); | |||||
// } catch (InterruptedException e) { | |||||
// e.printStackTrace(); | |||||
// } | |||||
return CalcTurnBackId(_TurnBackTimeTick); | return CalcTurnBackId(_TurnBackTimeTick); | ||||
} | } | ||||
@@ -214,6 +215,11 @@ public class SnowWorkerM1 implements ISnowWorker { | |||||
long tempTimeTicker = GetCurrentTimeTick(); | long tempTimeTicker = GetCurrentTimeTick(); | ||||
while (tempTimeTicker <= _LastTimeTick) { | while (tempTimeTicker <= _LastTimeTick) { | ||||
try { | |||||
Thread.sleep(1); | |||||
} catch (InterruptedException e) { | |||||
e.printStackTrace(); | |||||
} | |||||
tempTimeTicker = GetCurrentTimeTick(); | tempTimeTicker = GetCurrentTimeTick(); | ||||
} | } | ||||
@@ -227,4 +233,3 @@ public class SnowWorkerM1 implements ISnowWorker { | |||||
} | } | ||||
} | } | ||||
} | } | ||||
@@ -11,7 +11,6 @@ import com.github.yitter.contract.IdGeneratorOptions; | |||||
import com.github.yitter.core.SnowWorkerM1; | import com.github.yitter.core.SnowWorkerM1; | ||||
import com.github.yitter.core.SnowWorkerM2; | import com.github.yitter.core.SnowWorkerM2; | ||||
public class DefaultIdGenerator implements IIdGenerator { | public class DefaultIdGenerator implements IIdGenerator { | ||||
private static ISnowWorker _SnowWorker = null; | private static ISnowWorker _SnowWorker = null; | ||||
@@ -40,7 +39,8 @@ public class DefaultIdGenerator implements IIdGenerator { | |||||
maxWorkerIdNumber = 63; | maxWorkerIdNumber = 63; | ||||
} | } | ||||
if (options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber) { | if (options.WorkerId < 0 || options.WorkerId > maxWorkerIdNumber) { | ||||
throw new IdGeneratorException("WorkerId error. (range:[0, " + (maxWorkerIdNumber > 0 ? maxWorkerIdNumber : 63) + "]"); | |||||
throw new IdGeneratorException( | |||||
"WorkerId error. (range:[0, " + (maxWorkerIdNumber > 0 ? maxWorkerIdNumber : 63) + "]"); | |||||
} | } | ||||
// 4.SeqBitLength | // 4.SeqBitLength | ||||
@@ -62,6 +62,11 @@ public class DefaultIdGenerator implements IIdGenerator { | |||||
throw new IdGeneratorException("MinSeqNumber error. (range:[5, " + maxSeqNumber + "]"); | throw new IdGeneratorException("MinSeqNumber error. (range:[5, " + maxSeqNumber + "]"); | ||||
} | } | ||||
// 7.TopOverCostCount | |||||
if (options.TopOverCostCount < 0 || options.TopOverCostCount > 10000) { | |||||
throw new IdGeneratorException("TopOverCostCount error. (range:[0, 10000]"); | |||||
} | |||||
switch (options.Method) { | switch (options.Method) { | ||||
case 2: | case 2: | ||||
_SnowWorker = new SnowWorkerM2(options); | _SnowWorker = new SnowWorkerM2(options); | ||||
@@ -19,7 +19,6 @@ public class YitIdHelper { | |||||
return idGenInstance; | return idGenInstance; | ||||
} | } | ||||
/** | /** | ||||
* 设置参数,建议程序初始化时执行一次 | * 设置参数,建议程序初始化时执行一次 | ||||
*/ | */ | ||||
@@ -34,9 +33,12 @@ public class YitIdHelper { | |||||
* @return | * @return | ||||
*/ | */ | ||||
public static long nextId() throws IdGeneratorException { | public static long nextId() throws IdGeneratorException { | ||||
if (idGenInstance == null) { | |||||
idGenInstance = new DefaultIdGenerator(new IdGeneratorOptions((short) 1)); | |||||
} | |||||
// if (idGenInstance == null) { | |||||
// idGenInstance = new DefaultIdGenerator(new IdGeneratorOptions((short) 1)); | |||||
// } | |||||
if (idGenInstance == null) | |||||
throw new IdGeneratorException("Please initialize Yitter.IdGeneratorOptions first."); | |||||
return idGenInstance.newLong(); | return idGenInstance.newLong(); | ||||
} | } | ||||
@@ -26,7 +26,7 @@ public class GenTest { | |||||
long end = System.currentTimeMillis(); | long end = System.currentTimeMillis(); | ||||
long time = end - start; | long time = end - start; | ||||
System.out.println(id); | |||||
// System.out.println(id); | |||||
System.out.println("++++++++++++++++++++++++++++++++++++++++WorkerId: " | System.out.println("++++++++++++++++++++++++++++++++++++++++WorkerId: " | ||||
+ WorkerId + ", total: " + time + " ms"); | + WorkerId + ", total: " + time + " ms"); | ||||
@@ -12,7 +12,7 @@ public class StartUp { | |||||
* [不同CPU可能结果有差异,但相对大小不变] | * [不同CPU可能结果有差异,但相对大小不变] | ||||
* 默认配置下,最佳性能是5W/s-8W/s | * 默认配置下,最佳性能是5W/s-8W/s | ||||
*/ | */ | ||||
final static int genIdCount = 50000; | |||||
final static int genIdCount = 500000; | |||||
//1-漂移算法,2-传统算法 | //1-漂移算法,2-传统算法 | ||||
final static short method = 1; | final static short method = 1; | ||||
@@ -20,11 +20,12 @@ public class StartUp { | |||||
public static void main(String[] args) { | public static void main(String[] args) { | ||||
IdGeneratorOptions options = new IdGeneratorOptions(); | IdGeneratorOptions options = new IdGeneratorOptions(); | ||||
// options.WorkerIdBitLength = 6; | |||||
// options.SeqBitLength = 6; | |||||
// options.WorkerIdBitLength = 6; // 默认6 | |||||
options.SeqBitLength = 10; // 默认6 | |||||
// options.BaseTime = 1582206693000L; | // options.BaseTime = 1582206693000L; | ||||
options.Method = method; | options.Method = method; | ||||
options.WorkerId = 1; | options.WorkerId = 1; | ||||
// options.TopOverCostCount=2000; | |||||
// 首先测试一下 IdHelper 方法,获取单个Id | // 首先测试一下 IdHelper 方法,获取单个Id | ||||
YitIdHelper.setIdGenerator(options); | YitIdHelper.setIdGenerator(options); | ||||
@@ -38,7 +39,7 @@ public class StartUp { | |||||
while (true) { | while (true) { | ||||
genTest.GenStart(); | genTest.GenStart(); | ||||
Thread.sleep(1000); // 每隔1秒执行一次GenStart | Thread.sleep(1000); // 每隔1秒执行一次GenStart | ||||
System.out.println("Hello World! Java"); | |||||
// System.out.println("Hello World! Java"); | |||||
} | } | ||||
} catch (InterruptedException e) { | } catch (InterruptedException e) { | ||||
e.printStackTrace(); | e.printStackTrace(); | ||||
@@ -1,18 +1,13 @@ | |||||
// $Id$ | |||||
// vim:ft=javascript | // vim:ft=javascript | ||||
// If your extension references something external, use ARG_WITH | |||||
// ARG_WITH("snowdrift", "for snowdrift support", "no"); | |||||
// Otherwise, use ARG_ENABLE | |||||
ARG_ENABLE("snowdrift", "enable snowdrift support", "no"); | |||||
ARG_ENABLE('snowdrift', 'snowdrift support', 'no'); | |||||
if (PHP_SNOWDRIFT != "no") { | if (PHP_SNOWDRIFT != "no") { | ||||
AC_DEFINE('HAVE_SNOWDRIFT', 1, 'snowdrift support enabled'); | |||||
snowdrift_source_file="snowdrift.c\ | snowdrift_source_file="snowdrift.c\ | ||||
src/snowflake/snowflake.c\ | src/snowflake/snowflake.c\ | ||||
src/snowflake/shm.c\ | src/snowflake/shm.c\ | ||||
src/snowflake/spinlock.c | |||||
" | |||||
EXTENSION("snowdrift", $snowdrift_source_file, PHP_EXTNAME_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); | |||||
src/snowflake/spinlock.c" | |||||
EXTENSION("snowdrift", snowdrift_source_file, null, '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1'); | |||||
} | } | ||||
@@ -66,9 +66,8 @@ static int snowdrift_init() | |||||
shmctx.size = wid_num * sizeof(snowflake); | shmctx.size = wid_num * sizeof(snowflake); | ||||
if (shm_alloc(&shmctx) == -1) | if (shm_alloc(&shmctx) == -1) | ||||
{ | { | ||||
return FAILURE; | |||||
return FAILURE; | |||||
} | } | ||||
bzero(shmctx.addr, wid_num * sizeof(snowflake)); | |||||
sf = (snowflake *)shmctx.addr; | sf = (snowflake *)shmctx.addr; | ||||
int i; | int i; | ||||
for (i = 0; i < wid_num; i++) | for (i = 0; i < wid_num; i++) | ||||
@@ -92,7 +91,6 @@ static int snowdrift_init() | |||||
{ | { | ||||
return FAILURE; | return FAILURE; | ||||
} | } | ||||
bzero(shmctx.addr, sizeof(snowflake)); | |||||
sf = (snowflake *)shmctx.addr; | sf = (snowflake *)shmctx.addr; | ||||
sf->Method = SD_G(Method); | sf->Method = SD_G(Method); | ||||
sf->BaseTime = SD_G(BaseTime); | sf->BaseTime = SD_G(BaseTime); | ||||
@@ -138,7 +136,7 @@ PHP_METHOD(snowdrift, NextNumId) | |||||
{ | { | ||||
zend_long num = 1; | zend_long num = 1; | ||||
zend_long wid = SD_G(WorkerId); | zend_long wid = SD_G(WorkerId); | ||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l|l", &num, &wid) == FAILURE) | |||||
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|ll", &num, &wid) == FAILURE) | |||||
{ | { | ||||
RETURN_FALSE; | RETURN_FALSE; | ||||
} | } | ||||
@@ -1,65 +1,106 @@ | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <fcntl.h> | #include <fcntl.h> | ||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#ifdef WIN32 | |||||
#include "windows.h" | |||||
#else | |||||
#include <sys/mman.h> | #include <sys/mman.h> | ||||
#include <strings.h> | |||||
#endif | |||||
#include "shm.h" | #include "shm.h" | ||||
#ifdef MAP_ANON | |||||
#ifdef WIN32 | |||||
#define NAME "SnowDrift" | |||||
static HANDLE hMapFile; | |||||
int shm_alloc(struct shm *shm) | |||||
{ | |||||
shm->addr = (void *)mmap(NULL, shm->size, | |||||
PROT_READ | PROT_WRITE, | |||||
MAP_ANONYMOUS | MAP_SHARED, -1, 0); | |||||
int shm_alloc(struct shm* shm) { | |||||
hMapFile = CreateFileMapping( | |||||
INVALID_HANDLE_VALUE, | |||||
NULL, | |||||
PAGE_READWRITE, | |||||
0, | |||||
shm->size, | |||||
NAME | |||||
); | |||||
if (hMapFile == NULL) | |||||
{ | |||||
return 0; | |||||
} | |||||
LPVOID pBuffer = (LPTSTR)MapViewOfFile(hMapFile, FILE_MAP_ALL_ACCESS, 0, 0, shm->size); | |||||
if (pBuffer == NULL) | |||||
{ | |||||
CloseHandle(hMapFile); | |||||
return 0; | |||||
} | |||||
memset((char*)pBuffer, 0, shm->size); | |||||
shm->addr = (void*)pBuffer; | |||||
return 1; | |||||
} | |||||
void shm_free(struct shm* shm) { | |||||
UnmapViewOfFile(shm->addr); | |||||
CloseHandle(hMapFile); | |||||
} | |||||
if (shm->addr == NULL) | |||||
{ | |||||
return -1; | |||||
} | |||||
#elif defined(MAP_ANON) | |||||
return 0; | |||||
int shm_alloc(struct shm* shm) | |||||
{ | |||||
shm->addr = (void*)mmap(NULL, shm->size, | |||||
PROT_READ | PROT_WRITE, | |||||
MAP_ANONYMOUS | MAP_SHARED, -1, 0); | |||||
if (shm->addr == NULL) | |||||
{ | |||||
return -1; | |||||
} | |||||
bzero(shm->addr, shm->size); | |||||
return 0; | |||||
} | } | ||||
void shm_free(struct shm *shm) | |||||
void shm_free(struct shm* shm) | |||||
{ | { | ||||
if (shm->addr) | |||||
{ | |||||
munmap((void *)shm->addr, shm->size); | |||||
} | |||||
if (shm->addr) | |||||
{ | |||||
munmap((void*)shm->addr, shm->size); | |||||
} | |||||
} | } | ||||
#else | #else | ||||
int shm_alloc(struct shm *shm) | |||||
int shm_alloc(struct shm* shm) | |||||
{ | { | ||||
int fd; | |||||
fd = open("/dev/zero", O_RDWR); | |||||
if (fd == -1) | |||||
{ | |||||
return -1; | |||||
} | |||||
int fd; | |||||
shm->addr = (void *)mmap(NULL, shm->size, | |||||
PROT_READ | PROT_WRITE, | |||||
MAP_SHARED, fd, 0); | |||||
fd = open("/dev/zero", O_RDWR); | |||||
if (fd == -1) | |||||
{ | |||||
return -1; | |||||
} | |||||
close(fd); | |||||
shm->addr = (void*)mmap(NULL, shm->size, | |||||
PROT_READ | PROT_WRITE, | |||||
MAP_SHARED, fd, 0); | |||||
if (shm->addr == NULL) | |||||
{ | |||||
return -1; | |||||
} | |||||
close(fd); | |||||
return 0; | |||||
if (shm->addr == NULL) | |||||
{ | |||||
return -1; | |||||
} | |||||
bzero(shm->addr, shm->size); | |||||
return 0; | |||||
} | } | ||||
void shm_free(struct shm *shm) | |||||
void shm_free(struct shm* shm) | |||||
{ | { | ||||
if (shm->addr) | |||||
{ | |||||
munmap((void *)shm->addr, shm->size); | |||||
} | |||||
if (shm->addr) | |||||
{ | |||||
munmap((void*)shm->addr, shm->size); | |||||
} | |||||
} | } | ||||
#endif | #endif |
@@ -1,14 +1,16 @@ | |||||
#ifdef WIN32 | |||||
#include "windows.h" | |||||
#include <sys/timeb.h> | |||||
#else | |||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <sys/time.h> | #include <sys/time.h> | ||||
#include <time.h> | |||||
#endif | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include "snowflake.h" | #include "snowflake.h" | ||||
#include "spinlock.h" | #include "spinlock.h" | ||||
#if defined(WIN32) | |||||
#include "windows.h" | |||||
#endif | |||||
// static void EndOverCostAction(uint64_t useTimeTick, snowflake *flake); | // static void EndOverCostAction(uint64_t useTimeTick, snowflake *flake); | ||||
static inline uint64_t NextOverCostId(snowflake *flake); | static inline uint64_t NextOverCostId(snowflake *flake); | ||||
static inline uint64_t NextNormalId(snowflake *flake); | static inline uint64_t NextNormalId(snowflake *flake); | ||||
@@ -16,7 +18,7 @@ static inline uint64_t GetCurrentTimeTick(snowflake *flake); | |||||
static inline uint64_t GetNextTimeTick(snowflake *flake); | static inline uint64_t GetNextTimeTick(snowflake *flake); | ||||
static inline uint64_t CalcId(snowflake *flake); | static inline uint64_t CalcId(snowflake *flake); | ||||
static inline uint64_t CalcTurnBackId(snowflake *flake); | static inline uint64_t CalcTurnBackId(snowflake *flake); | ||||
static inline uint64_t GetCurrentTime(); | |||||
static inline uint64_t GetSysCurrentTime(); | |||||
int ncpu; | int ncpu; | ||||
uint16_t spin = 2048; | uint16_t spin = 2048; | ||||
@@ -24,102 +26,103 @@ uint32_t pid = 0; | |||||
void Config(snowflake *flake) | void Config(snowflake *flake) | ||||
{ | { | ||||
if (pid == 0) | |||||
{ | |||||
pid = (uint32_t)getpid(); | |||||
#if defined(WIN32) | |||||
SYSTEM_INFO sysInfo; | |||||
GetSystemInfo(&sysInfo); | |||||
ncpu = sysInfo.dwNumberOfProcessors; | |||||
if (pid == 0) | |||||
{ | |||||
#ifdef WIN32 | |||||
pid = (uint32_t)GetCurrentProcessId(); | |||||
SYSTEM_INFO sysInfo; | |||||
GetSystemInfo(&sysInfo); | |||||
ncpu = sysInfo.dwNumberOfProcessors; | |||||
#else | #else | ||||
ncpu = sysconf(_SC_NPROCESSORS_ONLN); | |||||
pid = (uint32_t)getpid(); | |||||
ncpu = sysconf(_SC_NPROCESSORS_ONLN); | |||||
#endif | #endif | ||||
if (ncpu <= 0) | |||||
{ | |||||
ncpu = 1; | |||||
} | |||||
} | |||||
if (flake->BaseTime == 0) | |||||
{ | |||||
flake->BaseTime = 1582136402000; | |||||
} | |||||
else if (flake->BaseTime < 631123200000 || flake->BaseTime > GetCurrentTime()) | |||||
{ | |||||
perror("BaseTime error."); | |||||
exit(1); | |||||
} | |||||
if (ncpu <= 0) | |||||
{ | |||||
ncpu = 1; | |||||
} | |||||
} | |||||
if (flake->BaseTime == 0) | |||||
{ | |||||
flake->BaseTime = 1582136402000; | |||||
} | |||||
else if (flake->BaseTime < 631123200000 || flake->BaseTime > GetSysCurrentTime()) | |||||
{ | |||||
perror("BaseTime error."); | |||||
exit(1); | |||||
} | |||||
// 2.WorkerIdBitLength | |||||
if (flake->WorkerIdBitLength <= 0) | |||||
{ | |||||
perror("WorkerIdBitLength error.(range:[1, 21])"); | |||||
exit(1); | |||||
} | |||||
if (flake->SeqBitLength + flake->WorkerIdBitLength > 22) | |||||
{ | |||||
perror("error:WorkerIdBitLength + SeqBitLength <= 22"); | |||||
exit(1); | |||||
} | |||||
else | |||||
{ | |||||
flake->WorkerIdBitLength = flake->WorkerIdBitLength <= 0 ? 6 : flake->WorkerIdBitLength; | |||||
} | |||||
// 2.WorkerIdBitLength | |||||
if (flake->WorkerIdBitLength <= 0) | |||||
{ | |||||
perror("WorkerIdBitLength error.(range:[1, 21])"); | |||||
exit(1); | |||||
} | |||||
if (flake->SeqBitLength + flake->WorkerIdBitLength > 22) | |||||
{ | |||||
perror("error:WorkerIdBitLength + SeqBitLength <= 22"); | |||||
exit(1); | |||||
} | |||||
else | |||||
{ | |||||
flake->WorkerIdBitLength = flake->WorkerIdBitLength <= 0 ? 6 : flake->WorkerIdBitLength; | |||||
} | |||||
// 3.WorkerId | |||||
uint32_t maxWorkerIdNumber = (1 << flake->WorkerIdBitLength) - 1; | |||||
if (maxWorkerIdNumber == 0) | |||||
{ | |||||
maxWorkerIdNumber = 63; | |||||
} | |||||
if (flake->WorkerId < 0 || flake->WorkerId > maxWorkerIdNumber) | |||||
{ | |||||
perror("WorkerId error. (range:[0, {2^WorkerIdBitLength-1]}"); | |||||
exit(1); | |||||
} | |||||
// 3.WorkerId | |||||
uint32_t maxWorkerIdNumber = (1 << flake->WorkerIdBitLength) - 1; | |||||
if (maxWorkerIdNumber == 0) | |||||
{ | |||||
maxWorkerIdNumber = 63; | |||||
} | |||||
if (flake->WorkerId < 0 || flake->WorkerId > maxWorkerIdNumber) | |||||
{ | |||||
perror("WorkerId error. (range:[0, {2^WorkerIdBitLength-1]}"); | |||||
exit(1); | |||||
} | |||||
// 4.SeqBitLength | |||||
if (flake->SeqBitLength < 2 || flake->SeqBitLength > 21) | |||||
{ | |||||
perror("SeqBitLength error. (range:[2, 21])"); | |||||
exit(1); | |||||
} | |||||
else | |||||
{ | |||||
flake->SeqBitLength = flake->SeqBitLength <= 0 ? 6 : flake->SeqBitLength; | |||||
} | |||||
// 4.SeqBitLength | |||||
if (flake->SeqBitLength < 2 || flake->SeqBitLength > 21) | |||||
{ | |||||
perror("SeqBitLength error. (range:[2, 21])"); | |||||
exit(1); | |||||
} | |||||
else | |||||
{ | |||||
flake->SeqBitLength = flake->SeqBitLength <= 0 ? 6 : flake->SeqBitLength; | |||||
} | |||||
// 5.MaxSeqNumber | |||||
uint32_t maxSeqNumber = (1 << flake->SeqBitLength) - 1; | |||||
if (maxSeqNumber == 0) | |||||
{ | |||||
maxSeqNumber = 63; | |||||
} | |||||
if (flake->MaxSeqNumber > maxSeqNumber) | |||||
{ | |||||
perror("MaxSeqNumber error. (range:[1, {2^SeqBitLength-1}]"); | |||||
exit(1); | |||||
} | |||||
else | |||||
{ | |||||
flake->MaxSeqNumber = flake->MaxSeqNumber <= 0 ? maxSeqNumber : flake->MaxSeqNumber; | |||||
} | |||||
// 5.MaxSeqNumber | |||||
uint32_t maxSeqNumber = (1 << flake->SeqBitLength) - 1; | |||||
if (maxSeqNumber == 0) | |||||
{ | |||||
maxSeqNumber = 63; | |||||
} | |||||
if (flake->MaxSeqNumber > maxSeqNumber) | |||||
{ | |||||
perror("MaxSeqNumber error. (range:[1, {2^SeqBitLength-1}]"); | |||||
exit(1); | |||||
} | |||||
else | |||||
{ | |||||
flake->MaxSeqNumber = flake->MaxSeqNumber <= 0 ? maxSeqNumber : flake->MaxSeqNumber; | |||||
} | |||||
// 6.MinSeqNumber | |||||
if (flake->MinSeqNumber < 5 || flake->MinSeqNumber > maxSeqNumber) | |||||
{ | |||||
perror("MinSeqNumber error. (range:[5, {MinSeqNumber}]"); | |||||
exit(1); | |||||
} | |||||
else | |||||
{ | |||||
flake->MinSeqNumber = flake->MinSeqNumber <= 0 ? 5 : flake->MinSeqNumber; | |||||
} | |||||
// 6.MinSeqNumber | |||||
if (flake->MinSeqNumber < 5 || flake->MinSeqNumber > maxSeqNumber) | |||||
{ | |||||
perror("MinSeqNumber error. (range:[5, {MinSeqNumber}]"); | |||||
exit(1); | |||||
} | |||||
else | |||||
{ | |||||
flake->MinSeqNumber = flake->MinSeqNumber <= 0 ? 5 : flake->MinSeqNumber; | |||||
} | |||||
// 7.Others | |||||
flake->TopOverCostCount = flake->TopOverCostCount <= 0 ? 2000 : flake->TopOverCostCount; | |||||
flake->_TimestampShift = flake->WorkerIdBitLength + flake->SeqBitLength; | |||||
flake->_CurrentSeqNumber = flake->MinSeqNumber; | |||||
flake->Method = flake->Method; | |||||
// 7.Others | |||||
flake->TopOverCostCount = flake->TopOverCostCount <= 0 ? 2000 : flake->TopOverCostCount; | |||||
flake->_TimestampShift = flake->WorkerIdBitLength + flake->SeqBitLength; | |||||
flake->_CurrentSeqNumber = flake->MinSeqNumber; | |||||
flake->Method = flake->Method; | |||||
} | } | ||||
// static inline void EndOverCostAction(uint64_t useTimeTick, snowflake *flake) | // static inline void EndOverCostAction(uint64_t useTimeTick, snowflake *flake) | ||||
@@ -132,158 +135,178 @@ void Config(snowflake *flake) | |||||
static inline uint64_t NextOverCostId(snowflake *flake) | static inline uint64_t NextOverCostId(snowflake *flake) | ||||
{ | { | ||||
uint64_t currentTimeTick = GetCurrentTimeTick(flake); | |||||
if (currentTimeTick > flake->_LastTimeTick) | |||||
{ | |||||
// EndOverCostAction(currentTimeTick, flake); | |||||
flake->_LastTimeTick = currentTimeTick; | |||||
flake->_CurrentSeqNumber = flake->MinSeqNumber; | |||||
flake->_IsOverCost = 0; | |||||
flake->_OverCostCountInOneTerm = 0; | |||||
// flake->_GenCountInOneTerm = 0; | |||||
return CalcId(flake); | |||||
} | |||||
if (flake->_OverCostCountInOneTerm > flake->TopOverCostCount) | |||||
{ | |||||
// EndOverCostAction(currentTimeTick, flake); | |||||
flake->_LastTimeTick = GetNextTimeTick(flake); | |||||
flake->_CurrentSeqNumber = flake->MinSeqNumber; | |||||
flake->_IsOverCost = 0; | |||||
flake->_OverCostCountInOneTerm = 0; | |||||
// flake->_GenCountInOneTerm = 0; | |||||
return CalcId(flake); | |||||
} | |||||
if (flake->_CurrentSeqNumber > flake->MaxSeqNumber) | |||||
{ | |||||
flake->_LastTimeTick++; | |||||
flake->_CurrentSeqNumber = flake->MinSeqNumber; | |||||
flake->_IsOverCost = 1; | |||||
flake->_OverCostCountInOneTerm++; | |||||
// flake->_GenCountInOneTerm++; | |||||
return CalcId(flake); | |||||
} | |||||
uint64_t currentTimeTick = GetCurrentTimeTick(flake); | |||||
if (currentTimeTick > flake->_LastTimeTick) | |||||
{ | |||||
// EndOverCostAction(currentTimeTick, flake); | |||||
flake->_LastTimeTick = currentTimeTick; | |||||
flake->_CurrentSeqNumber = flake->MinSeqNumber; | |||||
flake->_IsOverCost = 0; | |||||
flake->_OverCostCountInOneTerm = 0; | |||||
// flake->_GenCountInOneTerm = 0; | |||||
return CalcId(flake); | |||||
} | |||||
if (flake->_OverCostCountInOneTerm > flake->TopOverCostCount) | |||||
{ | |||||
// EndOverCostAction(currentTimeTick, flake); | |||||
flake->_LastTimeTick = GetNextTimeTick(flake); | |||||
flake->_CurrentSeqNumber = flake->MinSeqNumber; | |||||
flake->_IsOverCost = 0; | |||||
flake->_OverCostCountInOneTerm = 0; | |||||
// flake->_GenCountInOneTerm = 0; | |||||
return CalcId(flake); | |||||
} | |||||
if (flake->_CurrentSeqNumber > flake->MaxSeqNumber) | |||||
{ | |||||
flake->_LastTimeTick++; | |||||
flake->_CurrentSeqNumber = flake->MinSeqNumber; | |||||
flake->_IsOverCost = 1; | |||||
flake->_OverCostCountInOneTerm++; | |||||
// flake->_GenCountInOneTerm++; | |||||
return CalcId(flake); | |||||
} | |||||
// flake->_GenCountInOneTerm++; | |||||
return CalcId(flake); | |||||
// flake->_GenCountInOneTerm++; | |||||
return CalcId(flake); | |||||
} | } | ||||
static inline uint64_t NextNormalId(snowflake *flake) | static inline uint64_t NextNormalId(snowflake *flake) | ||||
{ | { | ||||
uint64_t currentTimeTick = GetCurrentTimeTick(flake); | |||||
if (currentTimeTick < flake->_LastTimeTick) | |||||
{ | |||||
if (flake->_TurnBackTimeTick < 1) | |||||
{ | |||||
flake->_TurnBackTimeTick = flake->_LastTimeTick - 1; | |||||
flake->_TurnBackIndex++; | |||||
if (flake->_TurnBackIndex > 4) | |||||
{ | |||||
flake->_TurnBackIndex = 1; | |||||
} | |||||
} | |||||
return CalcTurnBackId(flake); | |||||
} | |||||
if (flake->_TurnBackTimeTick > 0) | |||||
{ | |||||
flake->_TurnBackTimeTick = 0; | |||||
} | |||||
if (currentTimeTick > flake->_LastTimeTick) | |||||
{ | |||||
flake->_LastTimeTick = currentTimeTick; | |||||
flake->_CurrentSeqNumber = flake->MinSeqNumber; | |||||
return CalcId(flake); | |||||
} | |||||
if (flake->_CurrentSeqNumber > flake->MaxSeqNumber) | |||||
{ | |||||
// flake->_TermIndex++; | |||||
flake->_LastTimeTick++; | |||||
flake->_CurrentSeqNumber = flake->MinSeqNumber; | |||||
flake->_IsOverCost = 1; | |||||
flake->_OverCostCountInOneTerm = 1; | |||||
// flake->_GenCountInOneTerm = 1; | |||||
return CalcId(flake); | |||||
} | |||||
return CalcId(flake); | |||||
uint64_t currentTimeTick = GetCurrentTimeTick(flake); | |||||
if (currentTimeTick < flake->_LastTimeTick) | |||||
{ | |||||
if (flake->_TurnBackTimeTick < 1) | |||||
{ | |||||
flake->_TurnBackTimeTick = flake->_LastTimeTick - 1; | |||||
flake->_TurnBackIndex++; | |||||
if (flake->_TurnBackIndex > 4) | |||||
{ | |||||
flake->_TurnBackIndex = 1; | |||||
} | |||||
} | |||||
return CalcTurnBackId(flake); | |||||
} | |||||
if (flake->_TurnBackTimeTick > 0) | |||||
{ | |||||
flake->_TurnBackTimeTick = 0; | |||||
} | |||||
if (currentTimeTick > flake->_LastTimeTick) | |||||
{ | |||||
flake->_LastTimeTick = currentTimeTick; | |||||
flake->_CurrentSeqNumber = flake->MinSeqNumber; | |||||
return CalcId(flake); | |||||
} | |||||
if (flake->_CurrentSeqNumber > flake->MaxSeqNumber) | |||||
{ | |||||
// flake->_TermIndex++; | |||||
flake->_LastTimeTick++; | |||||
flake->_CurrentSeqNumber = flake->MinSeqNumber; | |||||
flake->_IsOverCost = 1; | |||||
flake->_OverCostCountInOneTerm = 1; | |||||
// flake->_GenCountInOneTerm = 1; | |||||
return CalcId(flake); | |||||
} | |||||
return CalcId(flake); | |||||
} | } | ||||
static inline uint64_t GetCurrentTime() | |||||
static inline uint64_t GetSysCurrentTime() | |||||
{ | { | ||||
struct timeval t; | |||||
gettimeofday(&t, NULL); | |||||
return (uint64_t)(t.tv_sec * 1000 + t.tv_usec / 1000); | |||||
#ifdef WIN32 | |||||
FILETIME file_time; | |||||
GetSystemTimeAsFileTime(&file_time); | |||||
uint64_t time = ((uint64_t)file_time.dwLowDateTime) + ((uint64_t)file_time.dwHighDateTime << 32); | |||||
static const uint64_t EPOCH = ((uint64_t)116444736000000000ULL); | |||||
return (uint64_t)((time - EPOCH) / 10000LL); | |||||
#else | |||||
struct timeval t; | |||||
gettimeofday(&t, NULL); | |||||
return (uint64_t)(t.tv_sec * 1000 + t.tv_usec / 1000); | |||||
#endif | |||||
} | } | ||||
static inline uint64_t GetCurrentTimeTick(snowflake *flake) | static inline uint64_t GetCurrentTimeTick(snowflake *flake) | ||||
{ | { | ||||
return GetCurrentTime() - flake->BaseTime; | |||||
return GetSysCurrentTime() - flake->BaseTime; | |||||
} | } | ||||
static inline uint64_t GetNextTimeTick(snowflake *flake) | static inline uint64_t GetNextTimeTick(snowflake *flake) | ||||
{ | { | ||||
uint64_t tempTimeTicker = GetCurrentTimeTick(flake); | |||||
while (tempTimeTicker <= flake->_LastTimeTick) | |||||
{ | |||||
tempTimeTicker = GetCurrentTimeTick(flake); | |||||
} | |||||
return tempTimeTicker; | |||||
uint64_t tempTimeTicker = GetCurrentTimeTick(flake); | |||||
struct timespec delay; | |||||
delay.tv_sec = 0; | |||||
delay.tv_nsec = 500000; | |||||
while (1) | |||||
{ | |||||
tempTimeTicker = GetCurrentTimeTick(flake); | |||||
if (tempTimeTicker > flake->_LastTimeTick) | |||||
{ | |||||
break; | |||||
} | |||||
#ifdef WIN32 | |||||
SwitchToThread(); | |||||
#else | |||||
nanosleep(&delay, NULL); | |||||
#endif | |||||
} | |||||
return tempTimeTicker; | |||||
} | } | ||||
static inline uint64_t CalcId(snowflake *flake) | static inline uint64_t CalcId(snowflake *flake) | ||||
{ | { | ||||
uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_CurrentSeqNumber); | |||||
flake->_CurrentSeqNumber++; | |||||
return result; | |||||
uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_CurrentSeqNumber); | |||||
flake->_CurrentSeqNumber++; | |||||
return result; | |||||
} | } | ||||
static inline uint64_t CalcTurnBackId(snowflake *flake) | static inline uint64_t CalcTurnBackId(snowflake *flake) | ||||
{ | { | ||||
uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_TurnBackTimeTick); | |||||
flake->_TurnBackTimeTick--; | |||||
return result; | |||||
uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_TurnBackTimeTick); | |||||
flake->_TurnBackTimeTick--; | |||||
return result; | |||||
} | } | ||||
static inline uint64_t NextSonwId(snowflake *flake) | static inline uint64_t NextSonwId(snowflake *flake) | ||||
{ | { | ||||
uint64_t currentTimeTick = GetCurrentTimeTick(flake); | |||||
if (flake->_LastTimeTick == currentTimeTick) | |||||
{ | |||||
flake->_CurrentSeqNumber++; | |||||
if (flake->_CurrentSeqNumber > flake->MaxSeqNumber) | |||||
{ | |||||
flake->_CurrentSeqNumber = flake->MinSeqNumber; | |||||
currentTimeTick = GetNextTimeTick(flake); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
flake->_CurrentSeqNumber = flake->MinSeqNumber; | |||||
} | |||||
flake->_LastTimeTick = currentTimeTick; | |||||
return (uint64_t)((currentTimeTick << flake->_TimestampShift) | (flake->WorkerId << flake->SeqBitLength) | flake->_CurrentSeqNumber); | |||||
uint64_t currentTimeTick = GetCurrentTimeTick(flake); | |||||
if (flake->_LastTimeTick == currentTimeTick) | |||||
{ | |||||
flake->_CurrentSeqNumber++; | |||||
if (flake->_CurrentSeqNumber > flake->MaxSeqNumber) | |||||
{ | |||||
flake->_CurrentSeqNumber = flake->MinSeqNumber; | |||||
currentTimeTick = GetNextTimeTick(flake); | |||||
} | |||||
} | |||||
else | |||||
{ | |||||
flake->_CurrentSeqNumber = flake->MinSeqNumber; | |||||
} | |||||
flake->_LastTimeTick = currentTimeTick; | |||||
return (uint64_t)((currentTimeTick << flake->_TimestampShift) | (flake->WorkerId << flake->SeqBitLength) | flake->_CurrentSeqNumber); | |||||
} | } | ||||
static inline uint64_t GetId(snowflake *flake) | static inline uint64_t GetId(snowflake *flake) | ||||
{ | { | ||||
return flake->Method == 1 ? (flake->_IsOverCost != 0 ? NextOverCostId(flake) : NextNormalId(flake)) : NextSonwId(flake); | |||||
return flake->Method == 1 ? (flake->_IsOverCost != 0 ? NextOverCostId(flake) : NextNormalId(flake)) : NextSonwId(flake); | |||||
} | } | ||||
uint64_t NextId(snowflake *flake) | uint64_t NextId(snowflake *flake) | ||||
{ | { | ||||
spin_lock(&flake->_Lock, pid); | |||||
uint64_t id = GetId(flake); | |||||
spin_unlock(&flake->_Lock, pid); | |||||
return id; | |||||
spin_lock(&flake->_Lock, pid); | |||||
uint64_t id = GetId(flake); | |||||
spin_unlock(&flake->_Lock, pid); | |||||
return id; | |||||
} | } | ||||
uint64_t *NextNumId(snowflake *flake, uint32_t num) | uint64_t *NextNumId(snowflake *flake, uint32_t num) | ||||
{ | { | ||||
uint64_t *arr = (uint64_t *)malloc(sizeof(uint64_t) * num); | |||||
spin_lock(&flake->_Lock, pid); | |||||
uint32_t i; | |||||
for (i = 0; i < num; i++) | |||||
{ | |||||
arr[i] = GetId(flake); | |||||
} | |||||
spin_unlock(&flake->_Lock, pid); | |||||
return arr; | |||||
uint64_t *arr = (uint64_t *)malloc(sizeof(uint64_t) * num); | |||||
spin_lock(&flake->_Lock, pid); | |||||
uint32_t i; | |||||
for (i = 0; i < num; i++) | |||||
{ | |||||
arr[i] = GetId(flake); | |||||
} | |||||
spin_unlock(&flake->_Lock, pid); | |||||
return arr; | |||||
} | } |
@@ -1,47 +1,73 @@ | |||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#ifdef WIN32 | |||||
#include "windows.h" | |||||
#else | |||||
#include <sched.h> | #include <sched.h> | ||||
#endif | |||||
#include "spinlock.h" | #include "spinlock.h" | ||||
extern int ncpu; | extern int ncpu; | ||||
extern int spin; | extern int spin; | ||||
void spin_lock(atomic_t *lock, uint32_t pid) | |||||
void spin_lock(atomic_t* lock, uint32_t pid) | |||||
{ | { | ||||
int i, n; | |||||
for (;;) | |||||
{ | |||||
if (*lock == 0 && | |||||
__sync_bool_compare_and_swap(lock, 0, pid)) | |||||
{ | |||||
return; | |||||
} | |||||
if (ncpu > 1) | |||||
{ | |||||
for (n = 1; n < spin; n <<= 1) | |||||
{ | |||||
for (i = 0; i < n; i++) | |||||
{ | |||||
__asm("pause"); | |||||
} | |||||
if (*lock == 0 && | |||||
__sync_bool_compare_and_swap(lock, 0, pid)) | |||||
{ | |||||
return; | |||||
} | |||||
} | |||||
} | |||||
sched_yield(); | |||||
} | |||||
int i, n; | |||||
for (;;) | |||||
{ | |||||
if (*lock == 0 && | |||||
#ifdef WIN32 | |||||
InterlockedCompareExchange(lock, pid, 0) == 0 | |||||
#else | |||||
__sync_bool_compare_and_swap(lock, 0, pid) | |||||
#endif | |||||
) | |||||
{ | |||||
return; | |||||
} | |||||
if (ncpu > 1) | |||||
{ | |||||
for (n = 1; n < spin; n <<= 1) | |||||
{ | |||||
for (i = 0; i < n; i++) | |||||
{ | |||||
#ifdef WIN32 | |||||
MemoryBarrier(); | |||||
#else | |||||
__asm("pause"); | |||||
#endif | |||||
} | |||||
if (*lock == 0 && | |||||
#ifdef WIN32 | |||||
InterlockedCompareExchange(lock, pid, 0) == 0 | |||||
#else | |||||
__sync_bool_compare_and_swap(lock, 0, pid) | |||||
#endif | |||||
) | |||||
{ | |||||
return; | |||||
} | |||||
} | |||||
} | |||||
#ifdef WIN32 | |||||
SwitchToThread(); | |||||
#else | |||||
sched_yield(); | |||||
#endif | |||||
} | |||||
} | } | ||||
void spin_unlock(atomic_t *lock, uint32_t pid) | |||||
void spin_unlock(atomic_t* lock, uint32_t pid) | |||||
{ | { | ||||
__sync_bool_compare_and_swap(lock, pid, 0); | |||||
#ifdef WIN32 | |||||
InterlockedCompareExchange(lock, 0, pid); | |||||
#else | |||||
__sync_bool_compare_and_swap(lock, pid, 0); | |||||
#endif | |||||
} | } |
@@ -0,0 +1,12 @@ | |||||
# ❄ idgenerator-Python(未完成) | |||||
## 运行环境 | |||||
Python 3.6+ | |||||
## 引用 包 | |||||
## 调用示例 | |||||
@@ -0,0 +1,31 @@ | |||||
import time | |||||
import traceback | |||||
from IdGeneratorOptions import IdGeneratorOptions | |||||
from SnowFlake import SnowFlake | |||||
from SnowFlakeM1 import SnowFlakeM1 | |||||
class DefaultIdGenerator(object): | |||||
def SetIdGernerator(self, options) : | |||||
if options.BaseTime < 100000 : | |||||
raise ValueError ("BaseTime error.") | |||||
self.SnowFlake= SnowFlakeM1(options) | |||||
def NextId(self): | |||||
return self.SnowFlake.NextId() | |||||
if __name__ == '__main__': | |||||
try: | |||||
options = IdGeneratorOptions(23) | |||||
options.BaseTime = 1231111111 | |||||
idgen = DefaultIdGenerator() | |||||
idgen.SetIdGernerator(options) | |||||
print (idgen.NextId()) | |||||
print (options.__dict__) | |||||
except ValueError as e: | |||||
print(e) | |||||
@@ -0,0 +1,30 @@ | |||||
import time | |||||
class IdGeneratorOptions(object): | |||||
def __init__(self, workerId = 0, workerIdBitLength = 6, seqBitLength = 6): | |||||
# 雪花计算方法,(1-漂移算法|2-传统算法),默认1。目前只实现了1。 | |||||
self.Method = 1 | |||||
# 基础时间(ms单位),不能超过当前系统时间 | |||||
self.BaseTime = 1288834974657 | |||||
# 机器码,必须由外部设定,最大值 2^WorkerIdBitLength-1 | |||||
self.WorkerId = workerId | |||||
# 机器码位长,默认值6,取值范围 [1, 15](要求:序列数位长+机器码位长不超过22) | |||||
self.WorkerIdBitLength = workerIdBitLength | |||||
# 序列数位长,默认值6,取值范围 [3, 21](要求:序列数位长+机器码位长不超过22) | |||||
self.SeqBitLength = seqBitLength | |||||
# 最大序列数(含),设置范围 [MinSeqNumber, 2^SeqBitLength-1],默认值0,表示最大序列数取最大值(2^SeqBitLength-1]) | |||||
self.MaxSeqNumber = 0 | |||||
# 最小序列数(含),默认值5,取值范围 [5, MaxSeqNumber],每毫秒的前5个序列数对应编号0-4是保留位,其中1-4是时间回拨相应预留位,0是手工新值预留位 | |||||
self.MinSeqNumber = 5 | |||||
# 最大漂移次数(含),默认2000,推荐范围500-10000(与计算能力有关) | |||||
self.TopOverCostCount = 2000 | |||||
@@ -0,0 +1,11 @@ | |||||
#!/usr/bin/python | |||||
# coding=UTF-8 | |||||
# 组件编号生成器 | |||||
class SnowFlake(object): | |||||
def __init__(self, options): | |||||
self.Options = options | |||||
def NextId(self): | |||||
return 0 |
@@ -0,0 +1,12 @@ | |||||
#!/usr/bin/python | |||||
# coding=UTF-8 | |||||
from SnowFlake import SnowFlake | |||||
# 组件编号生成器 | |||||
class SnowFlakeM1(SnowFlake): | |||||
def __init__(self, options): | |||||
self.Options = options | |||||
def NextId(self): | |||||
return self.Options.WorkerId |
@@ -222,9 +222,7 @@ QQ群:646049993 | |||||
#### 动态库下载 | #### 动态库下载 | ||||
下载链接1:https://github.com/yitter/IdGenerator/releases/download/reg_v1.0/regworkerid_lib_v1.0.zip | |||||
下载链接2:https://gitee.com/yitter/idgenerator/attach_files/662372/download/regworkerid_lib_v1.0.zip | |||||
下载链接1:https://github.com/yitter/IdGenerator/releases/download/v1.3.1/regworkerid_lib_v1.3.1.zip | |||||
#### 动态库接口定义 | #### 动态库接口定义 | ||||
``` | ``` | ||||
@@ -27,6 +27,7 @@ bld/ | |||||
**/.vs/ | **/.vs/ | ||||
# Uncomment if you have tasks that create the project's static files in wwwroot | # Uncomment if you have tasks that create the project's static files in wwwroot | ||||
#wwwroot/ | #wwwroot/ | ||||
.vscode | |||||
# MSTest test Results | # MSTest test Results | ||||
[Tt]est[Rr]esult*/ | [Tt]est[Rr]esult*/ | ||||
@@ -254,4 +255,4 @@ paket-files/ | |||||
target/ | target/ | ||||
# macOS | # macOS | ||||
.DS_Store | |||||
.DS_Store, |
@@ -2,10 +2,10 @@ | |||||
* 版权属于:yitter(yitter@126.com) | * 版权属于:yitter(yitter@126.com) | ||||
* 开源地址:https://github.com/yitter/idgenerator | * 开源地址:https://github.com/yitter/idgenerator | ||||
*/ | */ | ||||
use std::{thread}; | |||||
use crate::idgen::*; | |||||
use chrono::Utc; | use chrono::Utc; | ||||
use std::thread; | |||||
use std::thread::sleep; | use std::thread::sleep; | ||||
use crate::idgen::*; | |||||
// use lazy_static::lazy_static; | // use lazy_static::lazy_static; | ||||
pub struct SnowWorkerM1 { | pub struct SnowWorkerM1 { | ||||
@@ -42,26 +42,30 @@ impl SnowWorkerM1 { | |||||
} | } | ||||
pub fn SetOptions(&mut self, options: IdGeneratorOptions) { | pub fn SetOptions(&mut self, options: IdGeneratorOptions) { | ||||
// 1.BaseTime | // 1.BaseTime | ||||
if options.BaseTime == 0 { | if options.BaseTime == 0 { | ||||
self.BaseTime = 1582136402000; | self.BaseTime = 1582136402000; | ||||
} else if options.BaseTime < 631123200000 || options.BaseTime > Utc::now().timestamp_millis() { | |||||
} else if options.BaseTime < 631123200000 | |||||
|| options.BaseTime > Utc::now().timestamp_millis() | |||||
{ | |||||
panic!("BaseTime error."); | panic!("BaseTime error."); | ||||
} else { | } else { | ||||
self.BaseTime = options.BaseTime; | self.BaseTime = options.BaseTime; | ||||
} | } | ||||
// 2.WorkerIdBitLength | // 2.WorkerIdBitLength | ||||
if options.WorkerIdBitLength <= 0 | |||||
{ | |||||
if options.WorkerIdBitLength <= 0 { | |||||
panic!("WorkerIdBitLength error.(range:[1, 21])"); | panic!("WorkerIdBitLength error.(range:[1, 21])"); | ||||
} | } | ||||
if options.SeqBitLength + options.WorkerIdBitLength > 22 { | if options.SeqBitLength + options.WorkerIdBitLength > 22 { | ||||
panic!("error:WorkerIdBitLength + SeqBitLength <= 22"); | panic!("error:WorkerIdBitLength + SeqBitLength <= 22"); | ||||
} else { | } else { | ||||
// self.WorkerIdBitLength = options.WorkerIdBitLength; | // self.WorkerIdBitLength = options.WorkerIdBitLength; | ||||
self.WorkerIdBitLength = if options.WorkerIdBitLength <= 0 { 6 } else { options.WorkerIdBitLength }; | |||||
self.WorkerIdBitLength = if options.WorkerIdBitLength <= 0 { | |||||
6 | |||||
} else { | |||||
options.WorkerIdBitLength | |||||
}; | |||||
} | } | ||||
// 3.WorkerId | // 3.WorkerId | ||||
@@ -80,7 +84,11 @@ impl SnowWorkerM1 { | |||||
panic!("SeqBitLength error. (range:[2, 21])"); | panic!("SeqBitLength error. (range:[2, 21])"); | ||||
} else { | } else { | ||||
// self.SeqBitLength = options.SeqBitLength; | // self.SeqBitLength = options.SeqBitLength; | ||||
self.SeqBitLength = if options.SeqBitLength <= 0 { 6 } else { options.SeqBitLength }; | |||||
self.SeqBitLength = if options.SeqBitLength <= 0 { | |||||
6 | |||||
} else { | |||||
options.SeqBitLength | |||||
}; | |||||
} | } | ||||
// 5.MaxSeqNumber | // 5.MaxSeqNumber | ||||
@@ -91,7 +99,11 @@ impl SnowWorkerM1 { | |||||
if options.MaxSeqNumber < 0 || options.MaxSeqNumber > maxSeqNumber { | if options.MaxSeqNumber < 0 || options.MaxSeqNumber > maxSeqNumber { | ||||
panic!("MaxSeqNumber error. (range:[1, {}]", maxSeqNumber); | panic!("MaxSeqNumber error. (range:[1, {}]", maxSeqNumber); | ||||
} else { | } else { | ||||
self.MaxSeqNumber = if options.MaxSeqNumber == 0 { maxSeqNumber } else { options.MaxSeqNumber }; | |||||
self.MaxSeqNumber = if options.MaxSeqNumber == 0 { | |||||
maxSeqNumber | |||||
} else { | |||||
options.MaxSeqNumber | |||||
}; | |||||
} | } | ||||
// 6.MinSeqNumber | // 6.MinSeqNumber | ||||
@@ -102,8 +114,15 @@ impl SnowWorkerM1 { | |||||
// self.MinSeqNumber = if options.MinSeqNumber <= 0 { 5 } else { options.MinSeqNumber }; | // self.MinSeqNumber = if options.MinSeqNumber <= 0 { 5 } else { options.MinSeqNumber }; | ||||
} | } | ||||
// 7.Others | |||||
self.TopOverCostCount = if options.TopOverCostCount == 0 { 2000 } else { options.TopOverCostCount }; | |||||
// 7.TopOverCostCount | |||||
//self.TopOverCostCount = if options.TopOverCostCount == 0 { 2000 } else { options.TopOverCostCount }; | |||||
if options.TopOverCostCount < 0 || options.TopOverCostCount > 10000 { | |||||
panic!("TopOverCostCount error. (range:[0, 10000]"); | |||||
} else { | |||||
self.TopOverCostCount = options.TopOverCostCount; | |||||
} | |||||
// 8.Others | |||||
self._TimestampShift = self.WorkerIdBitLength + self.SeqBitLength; | self._TimestampShift = self.WorkerIdBitLength + self.SeqBitLength; | ||||
self._CurrentSeqNumber = self.MinSeqNumber; | self._CurrentSeqNumber = self.MinSeqNumber; | ||||
@@ -139,7 +158,11 @@ impl SnowWorkerM1 { | |||||
pub fn NextId(&mut self) -> i64 { | pub fn NextId(&mut self) -> i64 { | ||||
// println!("SeqBitLength: {}", self.SeqBitLength); | // println!("SeqBitLength: {}", self.SeqBitLength); | ||||
if self._IsOverCost { self.NextOverCostId() } else { self.NextNormalId() } | |||||
if self._IsOverCost { | |||||
self.NextOverCostId() | |||||
} else { | |||||
self.NextNormalId() | |||||
} | |||||
} | } | ||||
fn DoGenIdAction(&self, arg: OverCostActionArg) {} | fn DoGenIdAction(&self, arg: OverCostActionArg) {} | ||||
@@ -247,17 +270,17 @@ impl SnowWorkerM1 { | |||||
} | } | ||||
fn CalcId(&mut self, useTimeTick: i64) -> i64 { | fn CalcId(&mut self, useTimeTick: i64) -> i64 { | ||||
let result = (useTimeTick << self._TimestampShift) + | |||||
(self.WorkerId << self.SeqBitLength) as i64 + | |||||
(self._CurrentSeqNumber) as i64; | |||||
let result = (useTimeTick << self._TimestampShift) | |||||
+ (self.WorkerId << self.SeqBitLength) as i64 | |||||
+ (self._CurrentSeqNumber) as i64; | |||||
self._CurrentSeqNumber += 1; | self._CurrentSeqNumber += 1; | ||||
return result; | return result; | ||||
} | } | ||||
fn CalcTurnBackId(&mut self, useTimeTick: i64) -> i64 { | fn CalcTurnBackId(&mut self, useTimeTick: i64) -> i64 { | ||||
let result = (useTimeTick << self._TimestampShift) + | |||||
(self.WorkerId << self.SeqBitLength) as i64 + | |||||
(self._TurnBackIndex) as i64; | |||||
let result = (useTimeTick << self._TimestampShift) | |||||
+ (self.WorkerId << self.SeqBitLength) as i64 | |||||
+ (self._TurnBackIndex) as i64; | |||||
self._TurnBackTimeTick -= 1; | self._TurnBackTimeTick -= 1; | ||||
return result; | return result; | ||||
} | } | ||||
@@ -270,9 +293,11 @@ impl SnowWorkerM1 { | |||||
let mut tempTimeTicker = self.GetCurrentTimeTick(); | let mut tempTimeTicker = self.GetCurrentTimeTick(); | ||||
while tempTimeTicker <= self._LastTimeTick { | while tempTimeTicker <= self._LastTimeTick { | ||||
// 暂停1ms | |||||
sleep(std::time::Duration::from_millis(1)); | |||||
tempTimeTicker = self.GetCurrentTimeTick(); | tempTimeTicker = self.GetCurrentTimeTick(); | ||||
} | } | ||||
return tempTimeTicker; | return tempTimeTicker; | ||||
} | } | ||||
} | |||||
} |
@@ -1,16 +1,15 @@ | |||||
mod idgen; | mod idgen; | ||||
use chrono::Utc; | |||||
use idgen::*; | use idgen::*; | ||||
use std::thread; | use std::thread; | ||||
use chrono::Utc; | |||||
use std::time::Duration; | use std::time::Duration; | ||||
fn main() { | fn main() { | ||||
println!("Hello, world! Rust"); | println!("Hello, world! Rust"); | ||||
// 总执行次数 | // 总执行次数 | ||||
let times = 50000; | |||||
let times = 500000; | |||||
// 是否启用多线程测试 | // 是否启用多线程测试 | ||||
let multiThread = false; | let multiThread = false; | ||||
@@ -18,7 +17,7 @@ fn main() { | |||||
// 全局设置一次运行参数 | // 全局设置一次运行参数 | ||||
let mut options = IdGeneratorOptions::New(1); | let mut options = IdGeneratorOptions::New(1); | ||||
options.WorkerIdBitLength = 6; | options.WorkerIdBitLength = 6; | ||||
options.SeqBitLength = 6; | |||||
options.SeqBitLength = 10; | |||||
//... 可以继续设置其它 options 参数 | //... 可以继续设置其它 options 参数 | ||||
YitIdHelper::SetIdGenerator(options); | YitIdHelper::SetIdGenerator(options); | ||||
@@ -32,24 +31,29 @@ fn main() { | |||||
while i < times { | while i < times { | ||||
i += 1; | i += 1; | ||||
if multiThread { // 这是多线程 | |||||
thread::spawn(move || { | |||||
id = YitIdHelper::NextId(); | |||||
println!("{}, id: {}", i, id); | |||||
}); | |||||
} else { // 这是单线程 | |||||
id = YitIdHelper::NextId(); | |||||
} | |||||
} | |||||
YitIdHelper::NextId(); | |||||
println!("最后生成的id: {}", id); | |||||
if !multiThread { | |||||
// 多线程情况下,时间统计不准确 | |||||
let end = Utc::now().timestamp_millis(); | |||||
println!("单线程用时 {} ms", end - start); | |||||
// if multiThread { // 这是多线程 | |||||
// thread::spawn(move || { | |||||
// id = YitIdHelper::NextId(); | |||||
// println!("{}, id: {}", i, id); | |||||
// }); | |||||
// } else { // 这是单线程 | |||||
// id = YitIdHelper::NextId(); | |||||
// } | |||||
} | } | ||||
thread::sleep(std::time::Duration::from_millis(2000)); | |||||
let end = Utc::now().timestamp_millis(); | |||||
println!("单线程用时 {} ms", end - start); | |||||
// println!("最后生成的id: {}", id); | |||||
// if !multiThread { | |||||
// // 多线程情况下,时间统计不准确 | |||||
// let end = Utc::now().timestamp_millis(); | |||||
// println!("单线程用时 {} ms", end - start); | |||||
// } | |||||
thread::sleep(std::time::Duration::from_millis(1000)); | |||||
} | } | ||||
} | } | ||||
@@ -71,6 +75,4 @@ fn set_redis() { | |||||
// }, | // }, | ||||
// Err(error) => println!("Unable to create Redis client: {}", error) | // Err(error) => println!("Unable to create Redis client: {}", error) | ||||
// } | // } | ||||
} | |||||
} |
@@ -68,14 +68,9 @@ typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; | |||||
extern "C" { | extern "C" { | ||||
#endif | #endif | ||||
extern __declspec(dllexport) void SetOptions(GoUint16 workerId); | |||||
extern __declspec(dllexport) GoUint64 NextId(); | |||||
// 注册一个 WorkerId,会先注销所有本机已注册的记录 | // 注册一个 WorkerId,会先注销所有本机已注册的记录 | ||||
extern __declspec(dllexport) GoInt32 RegisterOne(char* ip, GoInt32 port, char* password, GoInt32 maxWorkerId); | |||||
// 注册多个 WorkerId,会先注销所有本机已注册的记录 | |||||
extern __declspec(dllexport) int* RegisterMany(char* ip, GoInt32 port, char* password, GoInt32 maxWorkerId, GoInt32 totalCount); | |||||
extern __declspec(dllexport) GoInt32 RegisterOne(char* ip, GoInt32 port, char* password, GoInt32 maxWorkerId, GoInt database); | |||||
// 注销本机已注册的 WorkerId | // 注销本机已注册的 WorkerId | ||||
extern __declspec(dllexport) void UnRegister(); | extern __declspec(dllexport) void UnRegister(); | ||||