Compare commits
10 Commits
v1.3.3
...
73800b4f83
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73800b4f83 | ||
|
|
aeec09a32a | ||
|
|
0783aba37a | ||
|
|
10409330f3 | ||
|
|
b5ee773830 | ||
|
|
15cf09927b | ||
|
|
d12b8e9d00 | ||
|
|
04a13eee38 | ||
|
|
d97d3aa98f | ||
|
|
3c15cf9df2 |
@@ -113,7 +113,7 @@ static inline int64_t CalcId(SnowFlakeWorker *worker) {
|
||||
|
||||
static inline int64_t CalcTurnBackId(SnowFlakeWorker *worker) {
|
||||
uint64_t result = (worker->_LastTimeTick << worker->_TimestampShift) | (worker->WorkerId << worker->SeqBitLength) |
|
||||
(worker->_TurnBackTimeTick);
|
||||
(worker->_TurnBackIndex);
|
||||
worker->_TurnBackTimeTick--;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -36,8 +36,8 @@ func main() {
|
||||
// password: Redis连接密码
|
||||
// db: Redis指定存储库,示例:1
|
||||
// sentinelMasterName: Redis 哨兵模式下的服务名称,示例:mymaster,非哨兵模式传入空字符串即可
|
||||
// maxWorkerId: WorkerId 最大值,示例:63
|
||||
// minWorkerId: WorkerId 最小值,示例:30
|
||||
// maxWorkerId: WorkerId 最大值,示例:63
|
||||
// lifeTimeSeconds: WorkerId缓存时长(秒,3的倍数)
|
||||
//export RegisterOne
|
||||
func RegisterOne(address *C.char, password *C.char, db int, sentinelMasterName *C.char, minWorkerId int32, maxWorkerId int32, lifeTimeSeconds int32) int32 {
|
||||
@@ -90,11 +90,11 @@ func Validate(workerId int32) int32 {
|
||||
// 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
|
||||
// go build -o ./target/workeridgo.dll -buildmode=c-shared main.go
|
||||
// // go build -o ./target/workeridgo.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
|
||||
// go build -o ./target/workeridgo.so -buildmode=c-shared main.go
|
||||
// go build -o ./target/workeridgo.so -buildmode=c-shared main.go reg.go
|
||||
|
||||
// https://books.studygolang.com/advanced-go-programming-book/ch2-cgo/ch2-09-static-shared-lib.html
|
||||
|
||||
@@ -261,7 +261,7 @@ static inline uint64_t CalcId(snowflake *flake)
|
||||
|
||||
static inline uint64_t CalcTurnBackId(snowflake *flake)
|
||||
{
|
||||
uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_TurnBackTimeTick);
|
||||
uint64_t result = (flake->_LastTimeTick << flake->_TimestampShift) + (flake->WorkerId << flake->SeqBitLength) + (flake->_TurnBackIndex );
|
||||
flake->_TurnBackTimeTick--;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
extern int ncpu;
|
||||
extern int spin;
|
||||
|
||||
void spin_lock(atomic_t* lock, uint32_t pid)
|
||||
void spin_lock(atomic_t *lock, uint32_t pid)
|
||||
{
|
||||
int i, n;
|
||||
|
||||
@@ -22,8 +22,8 @@ void spin_lock(atomic_t* lock, uint32_t pid)
|
||||
InterlockedCompareExchange(lock, pid, 0) == 0
|
||||
#else
|
||||
__sync_bool_compare_and_swap(lock, 0, pid)
|
||||
#endif
|
||||
)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -36,11 +36,7 @@ void spin_lock(atomic_t* lock, uint32_t pid)
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
{
|
||||
#ifdef WIN32
|
||||
MemoryBarrier();
|
||||
#else
|
||||
__asm("pause");
|
||||
#endif
|
||||
atomic_cpu_pause();
|
||||
}
|
||||
|
||||
if (*lock == 0 &&
|
||||
@@ -48,8 +44,8 @@ void spin_lock(atomic_t* lock, uint32_t pid)
|
||||
InterlockedCompareExchange(lock, pid, 0) == 0
|
||||
#else
|
||||
__sync_bool_compare_and_swap(lock, 0, pid)
|
||||
#endif
|
||||
)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -63,11 +59,11 @@ void spin_lock(atomic_t* lock, uint32_t pid)
|
||||
}
|
||||
}
|
||||
|
||||
void spin_unlock(atomic_t* lock, uint32_t pid)
|
||||
void spin_unlock(atomic_t *lock, uint32_t pid)
|
||||
{
|
||||
#ifdef WIN32
|
||||
InterlockedCompareExchange(lock, 0, pid);
|
||||
#else
|
||||
__sync_bool_compare_and_swap(lock, pid, 0);
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -8,4 +8,14 @@ extern void spin_lock(atomic_t *lock, uint32_t pid);
|
||||
|
||||
extern void spin_unlock(atomic_t *lock, uint32_t pid);
|
||||
|
||||
#if defined(WIN32)
|
||||
#define atomic_cpu_pause() MemoryBarrier();
|
||||
#elif defined(__x86_64__)
|
||||
#define atomic_cpu_pause() __asm__ __volatile__("pause")
|
||||
#elif defined(__aarch64__)
|
||||
#define atomic_cpu_pause() __asm__ __volatile__("yield")
|
||||
#else
|
||||
#define atomic_cpu_pause()
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,16 +1,15 @@
|
||||
--TEST--
|
||||
Check for snowdrift serial
|
||||
Check for snowdrift batch get unique
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("snowdrift")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$arr = [];
|
||||
$max = 1024;
|
||||
for ($i = 0; $i < $max; $i++) {
|
||||
$arr[$i] = SnowDrift::NextId();
|
||||
$max = 100000;
|
||||
foreach (SnowDrift::NextNumId($max) as $id) {
|
||||
$arr[$id] = '';
|
||||
}
|
||||
|
||||
var_dump(($arr[$max-1] - $arr[0]) == ($max-1));
|
||||
var_dump(count($arr));
|
||||
?>
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
int(100000)
|
||||
@@ -1,15 +0,0 @@
|
||||
--TEST--
|
||||
Check for snowdrift batch get unique
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("snowdrift")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$arr = [];
|
||||
$max = 100000;
|
||||
foreach (SnowDrift::NextNumId($max) as $id) {
|
||||
$arr[$id] = '';
|
||||
}
|
||||
var_dump(count($arr));
|
||||
?>
|
||||
--EXPECT--
|
||||
int(100000)
|
||||
17
README.md
17
README.md
@@ -221,22 +221,23 @@
|
||||
|
||||
#### 动态库下载
|
||||
|
||||
下载链接1:https://github.com/yitter/IdGenerator/releases/download/v1.3.1/regworkerid_lib_v1.3.1.zip
|
||||
下载链接:https://github.com/yitter/IdGenerator/releases/download/v1.3.3/workeridgo_lib_v1.3.3.zip
|
||||
|
||||
#### 动态库接口定义
|
||||
```
|
||||
// 注册一个 WorkerId,会先注销所有本机已注册的记录
|
||||
// ip: redis 服务器地址
|
||||
// port: redis 端口
|
||||
// password: redis 访问密码,可为空字符串“”
|
||||
// maxWorkerId: 最大 WorkerId
|
||||
extern GoInt32 RegisterOne(char* ip, GoInt32 port, char* password, GoInt32 maxWorkerId);
|
||||
// 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,非哨兵模式传入空字符串即可
|
||||
// minWorkerId: WorkerId 最小值,示例:30
|
||||
// maxWorkerId: WorkerId 最大值,示例:63
|
||||
// lifeTimeSeconds: WorkerId缓存时长(秒,3的倍数),推荐值15
|
||||
extern GoInt32 RegisterOne(char* server, char* password, GoInt32 db, char* sentinelMasterName, GoInt32 minWorkerId, GoInt32 maxWorkerId, GoInt32 lifeTimeSeconds);
|
||||
|
||||
// 注销本机已注册的 WorkerId
|
||||
extern void UnRegister();
|
||||
|
||||
// 检查本地WorkerId是否有效(0-有效,其它-无效)
|
||||
extern GoInt32 Validate(GoInt32 workerId);
|
||||
```
|
||||
|
||||
## 已实现的语言
|
||||
|
||||
101
Tools/AutoRegisterWorkerId/lib/workeridgo.h
Normal file
101
Tools/AutoRegisterWorkerId/lib/workeridgo.h
Normal file
@@ -0,0 +1,101 @@
|
||||
/* 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
|
||||
|
||||
|
||||
// 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,非哨兵模式传入空字符串即可
|
||||
// minWorkerId: WorkerId 最小值,示例:30
|
||||
// maxWorkerId: WorkerId 最大值,示例:63
|
||||
// lifeTimeSeconds: WorkerId缓存时长(秒,3的倍数)
|
||||
extern __declspec(dllexport) GoInt32 RegisterOne(char* address, char* password, GoInt db, char* sentinelMasterName, GoInt32 minWorkerId, GoInt32 maxWorkerId, GoInt32 lifeTimeSeconds);
|
||||
|
||||
// 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
|
||||
// minWorkerId: WorkerId 最小值,示例:30
|
||||
// totalCount: 获取N个WorkerId,示例:5
|
||||
// lifeTimeSeconds: WorkerId缓存时长(秒,3的倍数)
|
||||
extern __declspec(dllexport) GoSlice RegisterMany(char* address, char* password, GoInt db, char* sentinelMasterName, GoInt32 minWorkerId, GoInt32 maxWorkerId, GoInt32 totalCount, GoInt32 lifeTimeSeconds);
|
||||
|
||||
// UnRegister 注销本机已注册的 WorkerId
|
||||
extern __declspec(dllexport) void UnRegister();
|
||||
|
||||
// Validate 检查本地WorkerId是否有效(0-有效,其它-无效)
|
||||
extern __declspec(dllexport) GoInt32 Validate(GoInt32 workerId);
|
||||
|
||||
#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) GoInt32 RegisterOne(char* ip, GoInt32 port, char* password, GoInt32 maxWorkerId, GoInt database);
|
||||
|
||||
// 注销本机已注册的 WorkerId
|
||||
extern __declspec(dllexport) void UnRegister();
|
||||
|
||||
// 检查本地WorkerId是否有效(0-有效,其它-无效)
|
||||
extern __declspec(dllexport) GoInt32 Validate(GoInt32 workerId);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
@@ -115,7 +115,7 @@ export class snowflakeIdv1 {
|
||||
|
||||
// 5.MaxSeqNumber
|
||||
if (options.maxSeqNumber == undefined || options.maxSeqNumber <= 0)
|
||||
options.maxSeqNumber = (1 << options.SeqBitLength) - 1
|
||||
options.maxSeqNumber = (1 << options.seqBitLength) - 1
|
||||
|
||||
// 6.MinSeqNumber
|
||||
const MinSeqNumber = 5
|
||||
|
||||
Reference in New Issue
Block a user