@@ -252,6 +252,7 @@ paket-files/ | |||
# JetBrains Rider | |||
.idea/ | |||
*.sln.iml | |||
#target/ | |||
# macOS | |||
@@ -1,8 +1,8 @@ | |||
# idgenerator | |||
## ±àÒë˵Ã÷ | |||
## 编译说明 | |||
1.ĬÈÏÊÇ Linux »·¾³£¬Óà CMake¡£ | |||
1.默认是 Linux 环境,用 CMake。 | |||
2.Èç¹ûÊÇ Windows »·¾³£¬ÒªÓà Cygwin »ò MinGW¡£ | |||
2.如果是 Windows 环境,�用 Cygwin 或 MinGW。 | |||
@@ -1,35 +1,43 @@ | |||
# idgenerator | |||
## | |||
Go集成专项工程入口:https://gitee.com/yitter/idgenerator-go | |||
后文内容以 Go 专项工程为准。 | |||
## Go环境 | |||
1.SDK,go1.16 | |||
2.启用 Go-Modules | |||
``` | |||
go env -w GO111MODULE=on | |||
go env -w GOPROXY=https://goproxy.cn,https://goproxy.io,direct | |||
``` | |||
## Go代码示例 | |||
``` | |||
var yid = idgen.YitIdHelper{} | |||
fmt.Println(yid.NextId()) | |||
// 方法二:自定义参数 | |||
var options = contract.NewIdGeneratorOptions(1) | |||
//options.WorkerIdBitLength = 6 | |||
//options.SeqBitLength = 6 | |||
//options.TopOverCostCount = 2000 | |||
//options.BaseTime = time.Date(2020, 2, 20, 2, 20, 2, 20, time.UTC).UnixNano() / 1e6 | |||
yid.SetIdGenerator(options) | |||
``` | |||
# 鉂勶笍 idenerator-go | |||
## 浠嬬粛 | |||
椤圭洰鏇村�浠嬬粛鍙傜収锛歨ttps://github.com/yitter/idgenerator | |||
## Go鐜�� | |||
1.SDK锛実o1.14 | |||
2.鍚�敤 Go-Modules | |||
``` | |||
go env -w GO111MODULE=on | |||
go env -w GOPROXY=https://goproxy.cn,https://goproxy.io,direct | |||
``` | |||
3. 瀹夎�鏂瑰紡 | |||
``` | |||
go get -u -v github.com/yitter/idgenerator-go | |||
``` | |||
鎴� go.mod 涓�坊鍔犲紩鐢� | |||
``` | |||
require github.com/yitter/idgenerator-go v1.2.0 | |||
``` | |||
## Go浠g爜绀轰緥 | |||
``` | |||
// 瀹氫箟鍙傛暟 | |||
var options = idgen.NewIdGeneratorOptions(1) | |||
options.WorkerId = 1 | |||
options.WorkerIdBitLength = 6 | |||
options.SeqBitLength = 6 | |||
// ... | |||
idgen.SetIdGenerator(options) | |||
// 璋冪敤鏂规硶鐢熸垚Id | |||
var id = idgen.NextId() | |||
``` | |||
## 浠g爜璐$尞鑰�(鎸夋椂闂撮『搴�) | |||
guoyahao | amuluowin | houseme |
@@ -1,6 +1,6 @@ | |||
module yitidgen | |||
go 1.16 | |||
go 1.14 | |||
require ( | |||
github.com/go-redis/redis v6.15.9+incompatible | |||
@@ -7,18 +7,17 @@ | |||
package idgen | |||
import ( | |||
"strconv" | |||
"time" | |||
"yitidgen/contract" | |||
"yitidgen/core" | |||
) | |||
type DefaultIdGenerator struct { | |||
Options *contract.IdGeneratorOptions | |||
SnowWorker contract.ISnowWorker | |||
IdGeneratorException contract.IdGeneratorException | |||
Options *IdGeneratorOptions | |||
SnowWorker ISnowWorker | |||
IdGeneratorException IdGeneratorException | |||
} | |||
func NewDefaultIdGenerator(options *contract.IdGeneratorOptions) *DefaultIdGenerator { | |||
func NewDefaultIdGenerator(options *IdGeneratorOptions) *DefaultIdGenerator { | |||
if options == nil { | |||
panic("dig.Options error.") | |||
} | |||
@@ -32,9 +31,9 @@ func NewDefaultIdGenerator(options *contract.IdGeneratorOptions) *DefaultIdGener | |||
panic("error:WorkerIdBitLength + SeqBitLength <= 22") | |||
} | |||
maxWorkerIdNumber := uint16(1<<options.WorkerIdBitLength) - 1 | |||
if options.WorkerId > maxWorkerIdNumber { | |||
panic("WorkerId error. (range:[1, " + string(maxWorkerIdNumber) + "]") | |||
maxWorkerIDNumber := uint16(1<<options.WorkerIdBitLength) - 1 | |||
if options.WorkerId > maxWorkerIDNumber { | |||
panic("WorkerId error. (range:[1, " + strconv.FormatUint(uint64(maxWorkerIDNumber), 10) + "]") | |||
} | |||
if options.SeqBitLength < 2 || options.SeqBitLength > 21 { | |||
@@ -43,22 +42,23 @@ func NewDefaultIdGenerator(options *contract.IdGeneratorOptions) *DefaultIdGener | |||
maxSeqNumber := uint32(1<<options.SeqBitLength) - 1 | |||
if options.MaxSeqNumber > maxSeqNumber { | |||
panic("MaxSeqNumber error. (range:[1, " + string(maxSeqNumber) + "]") | |||
panic("MaxSeqNumber error. (range:[1, " + strconv.FormatUint(uint64(maxSeqNumber), 10) + "]") | |||
} | |||
if options.MinSeqNumber > maxSeqNumber { | |||
panic("MinSeqNumber error. (range:[1, " + string(maxSeqNumber) + "]") | |||
panic("MinSeqNumber error. (range:[1, " + strconv.FormatUint(uint64(maxSeqNumber), 10) + "]") | |||
} | |||
var snowWorker contract.ISnowWorker | |||
var snowWorker ISnowWorker | |||
switch options.Method { | |||
case 1: | |||
snowWorker = core.NewSnowWorkerM1(options) | |||
snowWorker = NewSnowWorkerM1(options) | |||
case 2: | |||
snowWorker = core.NewSnowWorkerM2(options) | |||
snowWorker = NewSnowWorkerM2(options) | |||
default: | |||
snowWorker = core.NewSnowWorkerM1(options) | |||
snowWorker = NewSnowWorkerM1(options) | |||
} | |||
if options.Method == 1 { | |||
@@ -4,7 +4,7 @@ | |||
* 代码修订:yitter | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package contract | |||
package idgen | |||
type IIdGenerator interface { | |||
NewLong() uint64 |
@@ -4,7 +4,7 @@ | |||
* 代码修订:yitter | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package contract | |||
package idgen | |||
type ISnowWorker interface { | |||
NextId() uint64 |
@@ -4,7 +4,7 @@ | |||
* 代码修订:yitter | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package contract | |||
package idgen | |||
import "fmt" | |||
@@ -4,7 +4,7 @@ | |||
* 代码修订:yitter | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package contract | |||
package idgen | |||
type IdGeneratorOptions struct { | |||
Method uint16 // 雪花计算方法,(1-漂移算法|2-传统算法),默认1 |
@@ -4,7 +4,7 @@ | |||
* 代码修订:yitter | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package contract | |||
package idgen | |||
type OverCostActionArg struct { | |||
ActionType int32 |
@@ -4,14 +4,14 @@ | |||
* 代码修订:yitter | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package core | |||
package idgen | |||
import ( | |||
"sync" | |||
"time" | |||
"yitidgen/contract" | |||
) | |||
// SnowWorkerM1 . | |||
type SnowWorkerM1 struct { | |||
BaseTime int64 //基础时间 | |||
WorkerId uint16 //机器码 | |||
@@ -32,7 +32,8 @@ type SnowWorkerM1 struct { | |||
sync.Mutex | |||
} | |||
func NewSnowWorkerM1(options *contract.IdGeneratorOptions) contract.ISnowWorker { | |||
// NewSnowWorkerM1 . | |||
func NewSnowWorkerM1(options *IdGeneratorOptions) ISnowWorker { | |||
var workerIdBitLength byte | |||
var seqBitLength byte | |||
var maxSeqNumber uint32 | |||
@@ -63,8 +64,10 @@ func NewSnowWorkerM1(options *contract.IdGeneratorOptions) contract.ISnowWorker | |||
} else { | |||
baseTime = 1582136402000 | |||
} | |||
timestampShift := (byte)(options.WorkerIdBitLength + options.SeqBitLength) | |||
currentSeqNumber := options.MinSeqNumber | |||
return &SnowWorkerM1{ | |||
BaseTime: baseTime, | |||
WorkerId: workerId, | |||
@@ -77,7 +80,8 @@ func NewSnowWorkerM1(options *contract.IdGeneratorOptions) contract.ISnowWorker | |||
_CurrentSeqNumber: currentSeqNumber} | |||
} | |||
func (m1 *SnowWorkerM1) DoGenIdAction(arg *contract.OverCostActionArg) { | |||
// DoGenIDAction . | |||
func (m1 *SnowWorkerM1) DoGenIdAction(arg *OverCostActionArg) { | |||
} | |||
@@ -128,10 +132,12 @@ func (m1 *SnowWorkerM1) NextOverCostId() uint64 { | |||
return m1.CalcId(m1._LastTimeTick) | |||
} | |||
m1._GenCountInOneTerm++ | |||
return m1.CalcId(m1._LastTimeTick) | |||
} | |||
// NextNormalID . | |||
func (m1 *SnowWorkerM1) NextNormalId() uint64 { | |||
currentTimeTick := m1.GetCurrentTimeTick() | |||
if currentTimeTick < m1._LastTimeTick { | |||
@@ -145,7 +151,8 @@ func (m1 *SnowWorkerM1) NextNormalId() uint64 { | |||
} | |||
m1.BeginTurnBackAction(m1._TurnBackTimeTick) | |||
} | |||
time.Sleep(time.Duration(10) * time.Millisecond) | |||
time.Sleep(time.Duration(1) * time.Millisecond) | |||
return m1.CalcTurnBackId(m1._TurnBackTimeTick) | |||
} | |||
// 时间追平时,_TurnBackTimeTick清零 | |||
@@ -169,26 +176,31 @@ func (m1 *SnowWorkerM1) NextNormalId() uint64 { | |||
return m1.CalcId(m1._LastTimeTick) | |||
} | |||
return m1.CalcId(m1._LastTimeTick) | |||
} | |||
// CalcID . | |||
func (m1 *SnowWorkerM1) CalcId(useTimeTick int64) uint64 { | |||
result := uint64(useTimeTick<<m1._TimestampShift) + uint64(m1.WorkerId<<m1.SeqBitLength) + uint64(m1._CurrentSeqNumber) | |||
m1._CurrentSeqNumber++ | |||
return result | |||
} | |||
// CalcTurnBackID . | |||
func (m1 *SnowWorkerM1) CalcTurnBackId(useTimeTick int64) uint64 { | |||
result := uint64(useTimeTick<<m1._TimestampShift) + uint64(m1.WorkerId<<m1.SeqBitLength) + uint64(m1._TurnBackIndex) | |||
m1._TurnBackTimeTick-- | |||
return result | |||
} | |||
// GetCurrentTimeTick . | |||
func (m1 *SnowWorkerM1) GetCurrentTimeTick() int64 { | |||
var millis = time.Now().UnixNano() / 1e6 | |||
return millis - m1.BaseTime | |||
} | |||
// GetNextTimeTick . | |||
func (m1 *SnowWorkerM1) GetNextTimeTick() int64 { | |||
tempTimeTicker := m1.GetCurrentTimeTick() | |||
for tempTimeTicker <= m1._LastTimeTick { | |||
@@ -197,6 +209,7 @@ func (m1 *SnowWorkerM1) GetNextTimeTick() int64 { | |||
return tempTimeTicker | |||
} | |||
// NextId . | |||
func (m1 *SnowWorkerM1) NextId() uint64 { | |||
m1.Lock() | |||
defer m1.Unlock() |
@@ -4,19 +4,18 @@ | |||
* 代码修订:yitter | |||
* 开源地址:https://gitee.com/yitter/idgenerator | |||
*/ | |||
package core | |||
package idgen | |||
import ( | |||
"fmt" | |||
"strconv" | |||
"yitidgen/contract" | |||
) | |||
type SnowWorkerM2 struct { | |||
*SnowWorkerM1 | |||
} | |||
func NewSnowWorkerM2(options *contract.IdGeneratorOptions) contract.ISnowWorker { | |||
func NewSnowWorkerM2(options *IdGeneratorOptions) ISnowWorker { | |||
return &SnowWorkerM2{ | |||
NewSnowWorkerM1(options).(*SnowWorkerM1), | |||
} |
@@ -8,7 +8,6 @@ package idgen | |||
import ( | |||
"sync" | |||
"yitidgen/contract" | |||
) | |||
//var yitIdHelper *YitIdHelper | |||
@@ -50,7 +49,7 @@ type YitIdHelper struct { | |||
// return yih.idGenInstance.NewLong() | |||
//} | |||
func SetIdGenerator(options *contract.IdGeneratorOptions) { | |||
func SetIdGenerator(options *IdGeneratorOptions) { | |||
singletonMutex.Lock() | |||
idGenerator = NewDefaultIdGenerator(options) | |||
singletonMutex.Unlock() | |||
@@ -59,7 +58,7 @@ func SetIdGenerator(options *contract.IdGeneratorOptions) { | |||
func NextId() uint64 { | |||
if idGenerator == nil { | |||
singletonMutex.Lock() | |||
options := contract.NewIdGeneratorOptions(1) | |||
options := NewIdGeneratorOptions(1) | |||
idGenerator = NewDefaultIdGenerator(options) | |||
singletonMutex.Unlock() | |||
} | |||
@@ -4,14 +4,13 @@ import ( | |||
"C" | |||
"fmt" | |||
"time" | |||
"yitidgen/contract" | |||
"yitidgen/idgen" | |||
"yitidgen/regworkerid" | |||
) | |||
///export SetOptions | |||
func SetOptions(workerId uint16) { | |||
var options = contract.NewIdGeneratorOptions(workerId) | |||
var options = idgen.NewIdGeneratorOptions(workerId) | |||
idgen.SetIdGenerator(options) | |||
} | |||
@@ -44,23 +43,21 @@ func main() { | |||
fmt.Println("注册的WorkerId:", regworkerid.RegisterWorkerId("localhost", 6379, "", 4)) | |||
return | |||
// 方法二:自定义参数 | |||
var options = contract.NewIdGeneratorOptions(1) | |||
var options = idgen.NewIdGeneratorOptions(1) | |||
options.WorkerIdBitLength = 6 | |||
options.SeqBitLength = 6 | |||
options.TopOverCostCount = 2000 | |||
options.BaseTime = time.Date(2020, 2, 20, 2, 20, 2, 20, time.UTC).UnixNano() / 1e6 | |||
idgen.SetIdGenerator(options) | |||
var genCount = 50000 | |||
for { | |||
var begin = time.Now().UnixNano() / 1e6 | |||
var begin = time.Now().UnixNano() / 1e3 | |||
for i := 0; i < genCount; i++ { | |||
idgen.NextId() | |||
} | |||
var end = time.Now().UnixNano() / 1e6 | |||
var end = time.Now().UnixNano() / 1e3 | |||
fmt.Println(end - begin) | |||
time.Sleep(time.Duration(1000) * time.Millisecond) | |||
@@ -70,6 +67,3 @@ func main() { | |||
// go build -o target\yitidgengo.dll -buildmode=c-shared main.go | |||
//var yid = idgen.YitIdHelper{} | |||
//yid.SetIdGenerator(options) | |||
//fmt.Println(yid.NextId()) |
@@ -1,75 +0,0 @@ | |||
/* Code generated by cmd/cgo; DO NOT EDIT. */ | |||
/* package command-line-arguments */ | |||
#line 1 "cgo-builtin-export-prolog" | |||
#include <stddef.h> /* for ptrdiff_t below */ | |||
#ifndef GO_CGO_EXPORT_PROLOGUE_H | |||
#define GO_CGO_EXPORT_PROLOGUE_H | |||
#ifndef GO_CGO_GOSTRING_TYPEDEF | |||
typedef struct { const char *p; ptrdiff_t n; } _GoString_; | |||
#endif | |||
#endif | |||
/* Start of preamble from import "C" comments. */ | |||
/* End of preamble from import "C" comments. */ | |||
/* Start of boilerplate cgo prologue. */ | |||
#line 1 "cgo-gcc-export-header-prolog" | |||
#ifndef GO_CGO_PROLOGUE_H | |||
#define GO_CGO_PROLOGUE_H | |||
typedef signed char GoInt8; | |||
typedef unsigned char GoUint8; | |||
typedef short GoInt16; | |||
typedef unsigned short GoUint16; | |||
typedef int GoInt32; | |||
typedef unsigned int GoUint32; | |||
typedef long long GoInt64; | |||
typedef unsigned long long GoUint64; | |||
typedef GoInt64 GoInt; | |||
typedef GoUint64 GoUint; | |||
typedef __SIZE_TYPE__ GoUintptr; | |||
typedef float GoFloat32; | |||
typedef double GoFloat64; | |||
typedef float _Complex GoComplex64; | |||
typedef double _Complex GoComplex128; | |||
/* | |||
static assertion to make sure the file is being used on architecture | |||
at least with matching size of GoInt. | |||
*/ | |||
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; | |||
#ifndef GO_CGO_GOSTRING_TYPEDEF | |||
typedef _GoString_ GoString; | |||
#endif | |||
typedef void *GoMap; | |||
typedef void *GoChan; | |||
typedef struct { void *t; void *v; } GoInterface; | |||
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; | |||
#endif | |||
/* End of boilerplate cgo prologue. */ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
extern __declspec(dllexport) GoUint64 NextId(); | |||
#ifdef __cplusplus | |||
} | |||
#endif |
@@ -1,75 +0,0 @@ | |||
/* Code generated by cmd/cgo; DO NOT EDIT. */ | |||
/* package command-line-arguments */ | |||
#line 1 "cgo-builtin-export-prolog" | |||
#include <stddef.h> /* for ptrdiff_t below */ | |||
#ifndef GO_CGO_EXPORT_PROLOGUE_H | |||
#define GO_CGO_EXPORT_PROLOGUE_H | |||
#ifndef GO_CGO_GOSTRING_TYPEDEF | |||
typedef struct { const char *p; ptrdiff_t n; } _GoString_; | |||
#endif | |||
#endif | |||
/* Start of preamble from import "C" comments. */ | |||
/* End of preamble from import "C" comments. */ | |||
/* Start of boilerplate cgo prologue. */ | |||
#line 1 "cgo-gcc-export-header-prolog" | |||
#ifndef GO_CGO_PROLOGUE_H | |||
#define GO_CGO_PROLOGUE_H | |||
typedef signed char GoInt8; | |||
typedef unsigned char GoUint8; | |||
typedef short GoInt16; | |||
typedef unsigned short GoUint16; | |||
typedef int GoInt32; | |||
typedef unsigned int GoUint32; | |||
typedef long long GoInt64; | |||
typedef unsigned long long GoUint64; | |||
typedef GoInt64 GoInt; | |||
typedef GoUint64 GoUint; | |||
typedef __SIZE_TYPE__ GoUintptr; | |||
typedef float GoFloat32; | |||
typedef double GoFloat64; | |||
typedef float _Complex GoComplex64; | |||
typedef double _Complex GoComplex128; | |||
/* | |||
static assertion to make sure the file is being used on architecture | |||
at least with matching size of GoInt. | |||
*/ | |||
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; | |||
#ifndef GO_CGO_GOSTRING_TYPEDEF | |||
typedef _GoString_ GoString; | |||
#endif | |||
typedef void *GoMap; | |||
typedef void *GoChan; | |||
typedef struct { void *t; void *v; } GoInterface; | |||
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; | |||
#endif | |||
/* End of boilerplate cgo prologue. */ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
extern __declspec(dllexport) GoUint64 NextId(); | |||
#ifdef __cplusplus | |||
} | |||
#endif |
@@ -1,83 +0,0 @@ | |||
/* Code generated by cmd/cgo; DO NOT EDIT. */ | |||
/* package command-line-arguments */ | |||
#line 1 "cgo-builtin-export-prolog" | |||
#include <stddef.h> /* for ptrdiff_t below */ | |||
#ifndef GO_CGO_EXPORT_PROLOGUE_H | |||
#define GO_CGO_EXPORT_PROLOGUE_H | |||
#ifndef GO_CGO_GOSTRING_TYPEDEF | |||
typedef struct { const char *p; ptrdiff_t n; } _GoString_; | |||
#endif | |||
#endif | |||
/* Start of preamble from import "C" comments. */ | |||
/* End of preamble from import "C" comments. */ | |||
/* Start of boilerplate cgo prologue. */ | |||
#line 1 "cgo-gcc-export-header-prolog" | |||
#ifndef GO_CGO_PROLOGUE_H | |||
#define GO_CGO_PROLOGUE_H | |||
typedef signed char GoInt8; | |||
typedef unsigned char GoUint8; | |||
typedef short GoInt16; | |||
typedef unsigned short GoUint16; | |||
typedef int GoInt32; | |||
typedef unsigned int GoUint32; | |||
typedef long long GoInt64; | |||
typedef unsigned long long GoUint64; | |||
typedef GoInt64 GoInt; | |||
typedef GoUint64 GoUint; | |||
typedef __SIZE_TYPE__ GoUintptr; | |||
typedef float GoFloat32; | |||
typedef double GoFloat64; | |||
typedef float _Complex GoComplex64; | |||
typedef double _Complex GoComplex128; | |||
/* | |||
static assertion to make sure the file is being used on architecture | |||
at least with matching size of GoInt. | |||
*/ | |||
typedef char _check_for_64_bit_pointer_matching_GoInt[sizeof(void*)==64/8 ? 1:-1]; | |||
#ifndef GO_CGO_GOSTRING_TYPEDEF | |||
typedef _GoString_ GoString; | |||
#endif | |||
typedef void *GoMap; | |||
typedef void *GoChan; | |||
typedef struct { void *t; void *v; } GoInterface; | |||
typedef struct { void *data; GoInt len; GoInt cap; } GoSlice; | |||
#endif | |||
/* End of boilerplate cgo prologue. */ | |||
#ifdef __cplusplus | |||
extern "C" { | |||
#endif | |||
// 注册一个新的WorkerId | |||
extern __declspec(dllexport) GoInt RegisterWorkerId(char* ip, GoInt port, char* password, GoInt maxWorkerId); | |||
// 注销WorkerId | |||
extern __declspec(dllexport) void UnRegisterWorkerId(); | |||
// 检查本地WorkerId是否有效(0-有效,其它-无效) | |||
extern __declspec(dllexport) GoInt ValidateLocalWorkerId(GoInt workerId); | |||
#ifdef __cplusplus | |||
} | |||
#endif |
@@ -2,7 +2,7 @@ | |||
## 转载及版权声明 | |||
<font color="#11aaff" size="5">©</font> 本人从未在博客园之外的网站,发表过关于本算法的长文,其它网站上存在的介绍文章,均属他人拷贝之作。 | |||
<font color="#11aaff" size="5">©</font> 本人从未在博客园之外的网站,发表过本算法长文,其它网站所现文章,均属他人拷贝之作。 | |||
<font color="#11aaff" size="5">©</font> 所有拷贝之作,均须保留项目开源链接,否则禁止转载。 | |||