社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
参考:https://redis.io/topics/distlock
代码:
package internal
import (
"errors"
"fmt"
"github.com/garyburd/redigo/redis"
)
type RedisLock struct {
//保存连接
Conn *redis.Conn
//生成随机value用于判断是否为自己上锁
uuid string
//锁状态
lock bool
}
/**
初始化
*/
func (redisLock *RedisLock) Init(protocolType string, ipAddress string, passWord string) error {
conn, err := createConn(protocolType, ipAddress, passWord)
if err != nil {
return err
}
redisLock.Conn = &conn
return nil
}
/**
创建redis连接
*/
func createConn(protocolType string, redisAddress string, password string) (redis.Conn, error) {
var conn redis.Conn
var err error
if password == "" {
conn, err = redis.Dial(protocolType, redisAddress)
} else {
conn, err = redis.Dial(protocolType, redisAddress, redis.DialPassword(password))
}
if err != nil {
return nil, err
}
return conn, nil
}
/**
尝试上锁
*/
func (redisLock *RedisLock) tryLock(key string) (bool, error) {
//如果判断已经在锁定状态则直接返回
if redisLock.lock {
return true, nil
}
//生成uuid
if redisLock.uuid == "" {
redisLock.uuid = NewUUID()
}
//NX 若Key存在则无法修改其值
//EX 过期时间 单位 秒
result, err := (*redisLock.Conn).Do("SET", key, redisLock.uuid, "NX", "EX", 300)
if err != nil {
return false, err
}
if result == "OK" {
redisLock.lock = true
return redisLock.lock, nil
}
return false, nil
}
/**
释放锁
*/
func (redisLock *RedisLock) removeLock(key string) (bool, error) {
if !redisLock.lock {
return false, errors.New("Unlocked ")
}
//判断锁是否为自己使用
script := "if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end"
//使用脚本方式
result, err := redis.Bool((*redisLock.Conn).Do("EVAL", script, 1, key, redisLock.uuid))
if err != nil {
return result, err
}
return result, nil
}
/**
锁模版
*/
func (redisLock *RedisLock) LockForRedis(key string, f func()) error {
result, err := redisLock.tryLock(key)
if err != nil {
return err
}
if !result {
return errors.New("continue")
}
fmt.Println("tryLock")
f()
result, err = redisLock.removeLock(key)
if err != nil {
return err
}
if result {
fmt.Println("removeLock")
}
return nil
}
guid:
package internal
import (
"github.com/typa01/go-utils"
)
func NewGUID() string {
return tsgutils.GUID()
}
func NewUUID() string {
return tsgutils.UUID()
}
test:
func main() {
fmt.Println("Start......")
count := 200
wg := sync.WaitGroup{}
wg.Add(count)
for i := 0; i < count; i++ {
go func() {
test()
//testLock()
wg.Done()
}()
//time.Sleep(time.Millisecond * 5)
}
wg.Wait()
fmt.Println(n)
fmt.Println("End......")
}
func test() {
n = n + 1
}
上述方式输出结果不确定:
Start......
193
End......
带有锁版本:
const ipAddress = "192.168.170.137:6379"
const protocolType = "tcp"
const passWord = "myredis123"
func main() {
fmt.Println("Start......")
count := 200
wg := sync.WaitGroup{}
wg.Add(count)
for i := 0; i < count; i++ {
go func() {
test()
testLock()
wg.Done()
}()
//time.Sleep(time.Millisecond * 5)
}
wg.Wait()
fmt.Println(n)
fmt.Println("End......")
}
func testLock() {
key := "myLockKey"
redisLock := new(internal.RedisLock)
redisLock.Init(protocolType, ipAddress, passWord)
result := redisLock.LockForRedis(key, test)
if result != nil {
fmt.Println(result)
}
}
func test() {
n = n + 1
}
输出:
Start......
continue
continue
continue
continue
continue
continue
continue
tryLock
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
tryLock
removeLock
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
removeLock
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
continue
2
End......
由于在锁定状态直接跳过所以只有拿到了锁的coroutine才有资格进行 n+n+1的操作,上述结果中存在98个continue所以结果为2是正确的。
延长for循环时间:
func main() {
fmt.Println("Start......")
count := 200
wg := sync.WaitGroup{}
wg.Add(count)
for i := 0; i < count; i++ {
go func() {
testLock()
wg.Done()
}()
time.Sleep(time.Millisecond )
}
wg.Wait()
fmt.Println(n)
fmt.Println("End......")
}
输出:
Start......
continue
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
continue
removeLock
tryLock
removeLock
tryLock
continue
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
continue
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
continue
removeLock
tryLock
removeLock
tryLock
continue
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
continue
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
continue
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
continue
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
continue
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
continue
removeLock
continue
tryLock
removeLock
tryLock
removeLock
continue
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
tryLock
removeLock
removeLock
tryLock
removeLock
tryLock
continue
removeLock
tryLock
removeLock
tryLock
continue
removeLock
tryLock
removeLock
tryLock
continue
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
continue
removeLock
tryLock
removeLock
continue
tryLock
removeLock
continue
tryLock
removeLock
continue
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
continue
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
continue
continue
tryLock
removeLock
tryLock
continue
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
continue
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
continue
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
tryLock
removeLock
174
End......
continue数量与实际计算结果:
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!