a Redisson like distributed locking implementation using Redis.
Explanation
go get github.com/cheerego/go-redissonMutex Example
- Exclusive Lock (X Lock).
- use it like std package sync.Mutex.
- not a reentrant lock that can't lock twice in a same goroutine.
RLock Example
- Exclusive Reentrant Lock.
- use it like java redisson.
- a reentrant lock that can lock many times in a same goroutine.
- tryLock,if waitTime > 0, wait
waitTimemilliseconds to try to obtain lock by while true and redis pub sub. - watchdog, if leaseTime = -1, start a time.Ticker(defaultWatchDogTime / 3) to renew lock expiration time.
g:=godisson.NewGodisson(rdb, godisson.WithWatchDogTimeout(30*time.Second))package main
import (
"github.com/cheerego/go-redisson""github.com/go-redis/redis/v8""github.com/pkg/errors""log""time"
)
funcmain() {
// create redis clientrdb:=redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password setDB: 0, // use default DB
})
deferrdb.Close()
g:=godisson.NewGodisson(rdb, godisson.WithWatchDogTimeout(30*time.Second))
test1(g)
test2(g)
}
// can't obtain lock in a same goroutinefunctest1(g*godisson.Godisson) {
m1:=g.NewMutex("godisson")
m2:=g.NewMutex("godisson")
err:=m1.TryLock(-1, 20000)
iferrors.Is(err, godisson.ErrLockNotObtained) {
log.Println("can't obtained lock")
} elseiferr!=nil {
log.Fatalln(err)
}
deferm1.Unlock()
// because waitTime = -1, waitTime < 0, try once, will return ErrLockNotObtainederr=m2.TryLock(-1, 20000)
iferrors.Is(err, godisson.ErrLockNotObtained) {
log.Println("m2 must not obtained lock")
} elseiferr!=nil {
log.Fatalln(err)
}
time.Sleep(10*time.Second)
}
functest2(g*godisson.Godisson) {
m1:=g.NewMutex("godisson")
m2:=g.NewMutex("godisson")
gofunc() {
err:=m1.TryLock(-1, 20000)
iferrors.Is(err, godisson.ErrLockNotObtained) {
log.Println("can't obtained lock")
} elseiferr!=nil {
log.Fatalln(err)
}
time.Sleep(10*time.Second)
m1.Unlock()
}()
// waitTime > 0, after 10 milliseconds will obtain the lockgofunc() {
time.Sleep(1*time.Second)
err:=m2.TryLock(15000, 20000)
iferrors.Is(err, godisson.ErrLockNotObtained) {
log.Println("m2 must not obtained lock")
} elseiferr!=nil {
log.Fatalln(err)
}
time.Sleep(10*time.Second)
m2.Unlock()
}()
time.Sleep(20*time.Second)
}
package main
import (
"github.com/cheerego/go-redisson""github.com/go-redis/redis/v8""log""time"
)
funcmain() {
// create redis clientrdb:=redis.NewClient(&redis.Options{
Addr: "localhost:6379",
Password: "", // no password setDB: 0, // use default DB
})
deferrdb.Close()
g:=godisson.NewGodisson(rdb, godisson.WithWatchDogTimeout(30*time.Second))
// lock with watchdog without retrylock:=g.NewRLock("godisson")
err:=lock.Lock()
iferr==godisson.ErrLockNotObtained {
log.Println("Could not obtain lock")
} elseiferr!=nil {
log.Fatalln(err)
}
deferlock.Unlock()
// lock with retry、watchdog// leaseTime value is -1, enable watchdoglock2:=g.NewRLock("godission-try-watchdog")
err=lock2.TryLock(20000, -1)
iferr==godisson.ErrLockNotObtained {
log.Println("Could not obtain lock")
} elseiferr!=nil {
log.Fatalln(err)
}
time.Sleep(10*time.Second)
deferlock.Unlock()
}