分布式锁有三种
1.乐观锁
2.redis锁
3.zookeeper锁
这次进行一个设计,redis分布式锁,只需要三种操作,增删查
首先一个redis连接池,由于会被导入,所以init
import (
"redigo/redis"
)
const (
SET_IF_NOT_EXIST = "NX" // 不存在则执行
SET_WITH_EXPIRE_TIME = "EX" // 过期时间(秒) PX 毫秒
SET_LOCK_SUCCESS = "OK" // 操作成功
DEL_LOCK_SUCCESS = 1 // lock 删除成功
DEL_LOCK_NON_EXISTENT = 0 // 删除lock key时,并不存在
)
var (
RdPool *redis.Pool
Conn redis.Conn
)
// NewRedisPool
func init(){
pool := &redis.Pool{
Dial: func() (conn redis.Conn, e error) {
return redis.Dial("tcp","localhost:6379")
},
MaxIdle: 10,
MaxActive: 20,
IdleTimeout: 100,
}
RdPool = pool
Conn = pool.Get()
}
添加lock锁
/*
redis 类型 字符串设置一个分布式锁 (哈希内部字段不支持过期判断,redis只支持***key过期)
@param key: 锁名,格式为 用户id_操作_方法
@param requestId: 客户端唯一id 用来指定锁不被其他线程(协程)删除
@param ex: 过期时间
*/
func AddLock(key,requestId string,ex int) bool {
msg,_ := redis.String(
Conn.Do("SET",key,requestId,SET_IF_NOT_EXIST,SET_WITH_EXPIRE_TIME,ex),
)
if msg == SET_LOCK_SUCCESS {
return true
}
return false
}
查
/*
获得redis分布式锁的值
@param key:redis类型字符串的key值
@param return: redis类型字符串的value
*/
func GetLock(key string) string {
msg,_ := redis.String(Conn.Do("GET",key))
return msg
}
删
/*
删除redis分布式锁
@param key:redis类型字符串的key值
@param requestId: 唯一值id,与value值对比,避免在分布式下其他实例删除该锁
*/
func DelLock(key ,requestId string) bool{
if GetLock(key) == requestId {
msg,_ := redis.Int64(Conn.Do("DEL",key))
// 避免操作时间过长,自动过期时再删除返回结果为0
if msg == DEL_LOCK_SUCCESS || msg == DEL_LOCK_NON_EXISTENT{
return true
}
return false
}
return false
}
实际操作
package main
import (
"fmt"
"github.com/google/uuid"
"./pool"
)
func main() {
uid, _ := uuid.NewUUID()
id := uid.String()
key := "用户id001_操作del_操作方法名DelComment"
if pool.AddLock(key, id, 3) {
fmt.Println("添加lock成功")
} else {
fmt.Println("添加lock失败")
}
if pool.GetLock(key) == id {
fmt.Println("相等")
}else {
fmt.Println("不相等")
}
if pool.DelLock(key,id){
fmt.Println("删除成功")
} else {
fmt.Println("删除失败")
}
}
实际结果
添加lock成功 相等 删除成功
参考资料:
https://www.cnblogs.com/linjiqin/p/8003838.html#!comments