From 61b9ea7fde44b3930f954269a33112628f1148d3 Mon Sep 17 00:00:00 2001 From: yitter Date: Sun, 12 Mar 2023 18:09:33 +0800 Subject: [PATCH] auto commit --- Go/regworkerid/main.go | 39 +++++---- Go/regworkerid/regworkerid/reghelper.go | 109 +++++++++++++++++------- 2 files changed, 101 insertions(+), 47 deletions(-) diff --git a/Go/regworkerid/main.go b/Go/regworkerid/main.go index 825f51f..6629698 100644 --- a/Go/regworkerid/main.go +++ b/Go/regworkerid/main.go @@ -10,6 +10,7 @@ import ( func main() { + //address := "192.168.1.207:6379" address := "127.0.0.1:6379" password := "" masterName := "" @@ -18,12 +19,12 @@ func main() { passChar := C.CString(password) masterNameChar := C.CString(masterName) - workerIdList := RegisterMany(addrChar, passChar, 4, masterNameChar, 3, 5) + workerIdList := RegisterMany(addrChar, passChar, 4, masterNameChar, 31, 60, 20, 15) for _, value := range workerIdList { fmt.Println("注册的WorkerId:", value) } - id := RegisterOne(addrChar, passChar, 4, masterNameChar, 0) + id := RegisterOne(addrChar, passChar, 4, masterNameChar, 31, 60, 15) fmt.Println("注册的WorkerId:", id) fmt.Println("end") @@ -36,14 +37,18 @@ func main() { // db: Redis指定存储库,示例:1 // sentinelMasterName: Redis 哨兵模式下的服务名称,示例:mymaster,非哨兵模式传入空字符串即可 // maxWorkerId: WorkerId 最大值,示例:63 +// minWorkerId: WorkerId 最小值,示例:30 +// lifeTimeSeconds: WorkerId缓存时长(秒,3的倍数) //export RegisterOne -func RegisterOne(address *C.char, password *C.char, db int, sentinelMasterName *C.char, maxWorkerId int32) int32 { +func RegisterOne(address *C.char, password *C.char, db int, sentinelMasterName *C.char, minWorkerId int32, maxWorkerId int32, lifeTimeSeconds int32) int32 { return regworkerid.RegisterOne(regworkerid.RegisterConf{ - Address: C.GoString(address), - Password: C.GoString(password), - DB: db, - MasterName: C.GoString(sentinelMasterName), - MaxWorkerId: maxWorkerId, + Address: C.GoString(address), + Password: C.GoString(password), + DB: db, + MasterName: C.GoString(sentinelMasterName), + MinWorkerId: minWorkerId, + MaxWorkerId: maxWorkerId, + LifeTimeSeconds: lifeTimeSeconds, }) } @@ -53,16 +58,20 @@ func RegisterOne(address *C.char, password *C.char, db int, sentinelMasterName * // db: Redis指定存储库,示例:1 // sentinelMasterName: Redis 哨兵模式下的服务名称,示例:mymaster,非哨兵模式传入空字符串即可 // maxWorkerId: WorkerId 最大值,示例:63 +// minWorkerId: WorkerId 最小值,示例:30 // totalCount: 获取N个WorkerId,示例:5 +// lifeTimeSeconds: WorkerId缓存时长(秒,3的倍数) //export RegisterMany -func RegisterMany(address *C.char, password *C.char, db int, sentinelMasterName *C.char, maxWorkerId int32, totalCount int32) []int32 { +func RegisterMany(address *C.char, password *C.char, db int, sentinelMasterName *C.char, minWorkerId int32, maxWorkerId int32, totalCount int32, lifeTimeSeconds 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, + Address: C.GoString(address), + Password: C.GoString(password), + DB: db, + MasterName: C.GoString(sentinelMasterName), + MinWorkerId: minWorkerId, + MaxWorkerId: maxWorkerId, + TotalCount: totalCount, + LifeTimeSeconds: lifeTimeSeconds, }) } diff --git a/Go/regworkerid/regworkerid/reghelper.go b/Go/regworkerid/regworkerid/reghelper.go index a68c4b5..2dafe25 100644 --- a/Go/regworkerid/regworkerid/reghelper.go +++ b/Go/regworkerid/regworkerid/reghelper.go @@ -3,11 +3,12 @@ package regworkerid import ( "context" "fmt" - "github.com/go-redis/redis/v8" "strconv" "strings" "sync" "time" + + "github.com/go-redis/redis/v8" ) var _client redis.UniversalClient @@ -15,32 +16,35 @@ var _ctx = context.Background() var _workerIdLock sync.Mutex var _workerIdList []int32 // 当前已注册的WorkerId -var _loopCount = 0 // 循环数量 -var _lifeIndex = -1 // WorkerId本地生命时序(本地多次注册时,生命时序会不同) -var _token = -1 // WorkerId远程注册时用的token,将存储在 IdGen:WorkerId:Value:xx 的值中(本功能暂未启用) +var _loopCount int32 = 0 // 循环数量 +var _lifeIndex int32 = -1 // WorkerId本地生命时序(本地多次注册时,生命时序会不同) +var _token int32 = -1 // WorkerId远程注册时用的token,将存储在 IdGen:WorkerId:Value:xx 的值中(本功能暂未启用) -var _WorkerIdLifeTimeSeconds = 15 // IdGen:WorkerId:Value:xx 的值在 redis 中的有效期(单位秒,最好是3的整数倍) -var _MaxLoopCount = 10 // 最大循环次数(无可用WorkerId时循环查找) -var _SleepMillisecondEveryLoop = 200 // 每次循环后,暂停时间 -var _MaxWorkerId int32 = 0 // 最大WorkerId值,超过此值从0开始 +var _WorkerIdLifeTimeSeconds int32 = 15 // IdGen:WorkerId:Value:xx 的值在 redis 中的有效期(单位秒,最好是3的整数倍) +var _MaxLoopCount int32 = 20 // 最大循环次数(无可用WorkerId时循环查找) +var _SleepMillisecondEveryLoop int32 = 200 // 每次循环后,暂停时间 +var _MaxWorkerId int32 = 0 // 最大WorkerId值,超过此值从_MinWorkerId开始 +var _MinWorkerId int32 = 0 // 最小WorkerId值 var _RedisConnString = "" var _RedisPassword = "" -var _RedisDB = 0 +var _RedisDB int = 0 var _RedisMasterName = "" -const _WorkerIdIndexKey string = "IdGen:WorkerId:Index" // redis 中的key -const _WorkerIdValueKeyPrefix string = "IdGen:WorkerId:Value:" // redis 中的key -const _WorkerIdFlag = "Y" // IdGen:WorkerId:Value:xx 的值(将来可用 _token 替代) -const _Log = false // 是否输出日志 +var _WorkerIdIndexKey string = "IdGen:WorkerId:Index" // redis 中的key +var _WorkerIdValueKeyPrefix string = "IdGen:WorkerId:Value:" // redis 中的key +var _WorkerIdFlag = "Y" // IdGen:WorkerId:Value:xx 的值(将来可用 _token 替代) +var _Log = false // 是否输出日志 type RegisterConf struct { - Address string // 注意:哨兵模式下,这里传入的是 Sentinel 节点,不是 Redis 节点 - Password string - DB int - MasterName string // 注意:哨兵模式下,这里必须传入 Sentinel 服务名称 - MaxWorkerId int32 - TotalCount int32 // 注意:仅对 RegisterMany 生效 + Address string // 注意:哨兵模式下,这里传入的是 Sentinel 节点,不是 Redis 节点 + Password string + DB int + MasterName string // 注意:哨兵模式下,这里必须传入 Sentinel 服务名称 + MaxWorkerId int32 + MinWorkerId int32 + TotalCount int32 // 注意:仅对 RegisterMany 生效 + LifeTimeSeconds int32 } func Validate(workerId int32) int32 { @@ -60,14 +64,30 @@ func Validate(workerId int32) int32 { } func UnRegister() { + _client = newRedisClient() + if _client == nil { + return + } + defer func() { + if _client != nil { + _ = _client.Close() + } + }() + + myUnRegister() +} + +func myUnRegister() { _workerIdLock.Lock() + // ToDo:在清除本地WorkerId之后,要删除redis键,并清除定时任务 _lifeIndex = -1 for _, value := range _workerIdList { if value > -1 { _client.Del(_ctx, _WorkerIdValueKeyPrefix+strconv.Itoa(int(value))) } } + _workerIdList = []int32{} _workerIdLock.Unlock() @@ -76,12 +96,13 @@ func UnRegister() { func autoUnRegister() { // 如果当前已注册过 WorkerId,则先注销,并终止先前的自动续期线程 if len(_workerIdList) > 0 { - UnRegister() + //UnRegister() + myUnRegister() } } func RegisterMany(conf RegisterConf) []int32 { - if conf.MaxWorkerId < 0 { + if conf.MaxWorkerId < 0 || conf.MinWorkerId > conf.MaxWorkerId { return []int32{-2} } @@ -91,13 +112,14 @@ func RegisterMany(conf RegisterConf) []int32 { conf.TotalCount = 1 } - autoUnRegister() - _MaxWorkerId = conf.MaxWorkerId + _MinWorkerId = conf.MinWorkerId _RedisConnString = conf.Address _RedisPassword = conf.Password _RedisDB = conf.DB _RedisMasterName = conf.MasterName + _WorkerIdLifeTimeSeconds = conf.LifeTimeSeconds + _client = newRedisClient() if _client == nil { return []int32{-1} @@ -107,6 +129,9 @@ func RegisterMany(conf RegisterConf) []int32 { _ = _client.Close() } }() + + autoUnRegister() + //_, err := _client.Ping(_ctx).Result() //if err != nil { // //panic("init redis error") @@ -142,18 +167,19 @@ func RegisterMany(conf RegisterConf) []int32 { } func RegisterOne(conf RegisterConf) int32 { - if conf.MaxWorkerId < 0 { + if conf.MaxWorkerId < 0 || conf.MinWorkerId > conf.MaxWorkerId { return -2 } - autoUnRegister() - _MaxWorkerId = conf.MaxWorkerId + _MinWorkerId = conf.MinWorkerId _RedisConnString = conf.Address _RedisPassword = conf.Password _RedisDB = conf.DB _RedisMasterName = conf.MasterName + _WorkerIdLifeTimeSeconds = conf.LifeTimeSeconds _loopCount = 0 + _client = newRedisClient() if _client == nil { return -3 @@ -173,6 +199,8 @@ func RegisterOne(conf RegisterConf) int32 { // } //} + autoUnRegister() + _lifeIndex++ var id = register(_lifeIndex) if id > -1 { @@ -183,7 +211,7 @@ func RegisterOne(conf RegisterConf) int32 { return id } -func register(lifeTime int) int32 { +func register(lifeTime int32) int32 { _loopCount = 0 return getNextWorkerId(lifeTime) } @@ -202,7 +230,7 @@ func newRedisClient() redis.UniversalClient { return client } -func getNextWorkerId(lifeTime int) int32 { +func getNextWorkerId(lifeTime int32) int32 { // 获取当前 WorkerIdIndex r, err := _client.Incr(_ctx, _WorkerIdIndexKey).Result() if err != nil { @@ -210,6 +238,13 @@ func getNextWorkerId(lifeTime int) int32 { } candidateId := int32(r) + + // 设置最小值 + if candidateId < _MinWorkerId { + candidateId = _MinWorkerId + setWorkerIdIndex(_MinWorkerId) + } + if _Log { fmt.Println("Begin candidateId:" + strconv.Itoa(int(candidateId))) } @@ -218,7 +253,8 @@ func getNextWorkerId(lifeTime int) int32 { if candidateId > _MaxWorkerId { if canReset() { // 当前应用获得重置 WorkerIdIndex 的权限 - setWorkerIdIndex(-1) + //setWorkerIdIndex(-1) + setWorkerIdIndex(_MinWorkerId - 1) endReset() // 此步有可能不被执行? _loopCount++ @@ -276,7 +312,7 @@ func getNextWorkerId(lifeTime int) int32 { } } -func extendLifeTime(lifeIndex int) { +func extendLifeTime(lifeIndex int32) { // 获取到可用 WorkerId 后,启用新线程,每隔 1/3个 _WorkerIdLifeTimeSeconds 时间,向服务器续期(延长一次 LifeTime) var myLifeIndex = lifeIndex @@ -288,6 +324,7 @@ func extendLifeTime(lifeIndex int) { _workerIdLock.Lock() // 如果临时变量 myLifeIndex 不等于 全局变量 _lifeIndex,表明全局状态被修改,当前线程可终止,不应继续操作 redis + // 还应主动释放 redis 键值缓存 if myLifeIndex != _lifeIndex { break } @@ -308,7 +345,7 @@ func extendLifeTime(lifeIndex int) { } } -func extendWorkerIdLifeTime(lifeIndex int, workerId int32) { +func extendWorkerIdLifeTime(lifeIndex int32, workerId int32) { var myLifeIndex = lifeIndex var myWorkerId = workerId @@ -344,11 +381,19 @@ func get(key string) (string, bool) { return r, true } +func del(key string) (int64, bool) { + r, err := _client.Del(_ctx, key).Result() + if err != nil { + return 0, false + } + return r, true +} + func set(key string, val string, expTime int32) { _client.Set(_ctx, key, val, time.Duration(expTime)*time.Second) } -func setWorkerIdIndex(val int) { +func setWorkerIdIndex(val int32) { _client.Set(_ctx, _WorkerIdIndexKey, val, 0) }