我使用go-redis distributed lock实现互斥访问,我的服务器是单线程服务器。但与此同时,许多请求都会获得distributed lock。
func (redisMgrPtr *RedisMgr) getLock(key string) (int32) {
encodeKey := transcoding.Base64Encode(key)
_, err := redisMgrPtr.redisClient.SetNX(redisMgrPtr.ctx,
encodeKey, 1, TIMEOUT).Result()
if err != nil {
return -1
}
return 0
}
func (redisMgrPtr *RedisMgr) delLock(key string, sessionId string) {
encodeKey := transcoding.Base64Encode(key)
redisMgrPtr.redisClient.Del(redisMgrPtr.ctx, encodeKey)
Log.Errorf("session[%s] del lock", sessionId)
}获取锁代码如下所示:
func (redisMgrPtr *RedisMgr) GetServer(name string, session string) () {
for {
locRes := redisMgrPtr.getLock(name)
if locRes == 0 {
break
} else {
time.Sleep(5 * time.Millisecond)
continue
}
}
defer redisMgrPtr.delLock(sceneLock, sessionId)
Log.Errorf("session[%s] get lock", sessionId)
// do something
}我发现有许多请求同时获取锁,结果是
2021-09-08T15:05:21.073+0800 session[51776955325] get lock
2021-09-08T15:05:21.073+0800 session[91776955325] get lock
2021-09-08T15:05:21.073+0800 session[71776955325] get lock我认为同时只有一个会话可以获得锁
发布于 2021-09-08 16:41:35
问题似乎出在lock函数上。它不检查该值是否存在,它只检查错误。
func (redisMgrPtr *RedisMgr) getLock(key string) (int32) {
encodeKey := transcoding.Base64Encode(key)
wasSet, err := redisMgrPtr.redisClient.SetNX(redisMgrPtr.ctx, encodeKey, 1, TIMEOUT).Result()
if err != nil || !wasSet {
return -1
}
return 0
}..。或者使用布尔值来简化推理:
func (redisMgrPtr *RedisMgr) getLock(key string) (ok bool) {
encodeKey := transcoding.Base64Encode(key)
wasSet, err := redisMgrPtr.redisClient.SetNX(redisMgrPtr.ctx, encodeKey, 1, TIMEOUT).Result()
return err == nil && wasSet
}使用布尔版本时,GetServer可能如下所示:
func (redisMgrPtr *RedisMgr) GetServer(name string, session string) () {
for {
if ok := redisMgrPtr.getLock(name); ok {
break
}
time.Sleep(5 * time.Millisecond)
}
defer redisMgrPtr.delLock(sceneLock, sessionId)
Log.Errorf("session[%s] get lock", sessionId)
// do something
}https://stackoverflow.com/questions/69101000
复制相似问题