Redis 分布式锁 安装 docker1
docker pull cgr.dev/chainguard/redis:latest
docker-compose1
2
3
4
5
6
7
version : '3.7'
services :
redis-lock :
image : cgr.dev/chainguard/redis:latest
container_name : redis-lock
ports :
- "6379:6379"
redsync 源码实现 v8 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
package main
import (
"fmt"
redis "github.com/go-redis/redis/v8"
redsync "github.com/go-redsync/redsync/v4"
goredis "github.com/go-redsync/redsync/v4/redis/goredis/v8"
"time"
)
func main () {
client := redis . NewClient ( & redis . Options {
Addr : "192.168.80.128:6379" ,
})
pool := goredis . NewPool ( client )
rs := redsync . New ( pool )
mutexname := "lock:1"
//创建基于key的互斥锁
var fn = func () {
mutex := rs . NewMutex ( mutexname , redsync . WithTries ( 1000 ))
// 对key进行
if err := mutex . Lock (); err != nil {
panic ( err )
}
// 模拟业务耗时
fmt . Println ( "ok" )
time . Sleep ( 1 * time . Second )
if ok , err := mutex . Unlock (); ! ok || err != nil {
panic ( "unlock failed" )
}
}
for i := 0 ; i < 30 ; i ++ {
// 模拟并发
go fn ()
}
select {}
}
v9 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
package main
import (
"fmt"
"github.com/go-redsync/redsync/v4"
"github.com/go-redsync/redsync/v4/redis/goredis/v9"
redis "github.com/redis/go-redis/v9"
"time"
)
func main () {
client := redis . NewClient ( & redis . Options {
Addr : "192.168.80.128:6379" ,
})
pool := goredis . NewPool ( client )
rs := redsync . New ( pool )
mutexname := "lock:1"
//创建基于key的互斥锁
var fn = func () {
mutex := rs . NewMutex ( mutexname , redsync . WithTries ( 1000 ))
// 对key进行
if err := mutex . Lock (); err != nil {
panic ( err )
}
// 获取锁后的业务逻辑处理.
fmt . Println ( "ok" )
time . Sleep ( 1 * time . Second )
// 释放互斥锁
if ok , err := mutex . Unlock (); ! ok || err != nil {
panic ( "unlock failed" )
}
}
for i := 0 ; i < 30 ; i ++ {
go fn ()
}
select {}
}
注意点初始化mutex的时候, 默认参数是重试32次,锁的超时时间是8秒,如果不满足业务需求,需要手动配置
关于延迟函数为什么要加入随机因子? 因为需要实现公平锁,如果没有随机,那么永远是先来的先抢到锁
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package redsync
// NewMutex returns a new distributed mutex with given name.
func ( r * Redsync ) NewMutex ( name string , options ... Option ) * Mutex {
m := & Mutex {
name : name ,
expiry : 8 * time . Second ,
tries : 32 ,
delayFunc : func ( tries int ) time . Duration {
return time . Duration ( rand . Intn ( maxRetryDelayMilliSec - minRetryDelayMilliSec ) + minRetryDelayMilliSec ) * time . Millisecond
},
genValueFunc : genValue ,
driftFactor : 0.01 ,
timeoutFactor : 0.05 ,
quorum : len ( r . pools ) / 2 + 1 ,
pools : r . pools ,
}
for _ , o := range options {
o . Apply ( m )
}
if m . shuffle {
randomPools ( m . pools )
}
return m
}