Simplified distributed locking implementation using Redis. For more information, please see examples.
Redislock supports liner and exponential backoff. One thing to not is the retry time with interval should be less than the overall ttl of the key.
import (
"fmt"
"time"
"github.com/verloop/redislock"
"github.com/garyburd/redigo/redis"
)
func main() {
// Connect to redis.
client := &redis.Pool{
MaxIdle: 3,
IdleTimeout: 240 * time.Second,
Dial: func() (redis.Conn, error) {
return redis.Dial("tcp", ":6379",
redis.DialDatabase(1))
},
}
// Create a new lock client.
locker := redislock.New(client)
// Try to obtain lock.
lock, err := locker.Obtain("my-key", 100*time.Millisecond, nil)
if err == redislock.ErrNotObtained {
fmt.Println("Could not obtain lock!")
} else if err != nil {
log.Fatalln(err)
}
// Don't forget to defer Release.
defer lock.Release()
fmt.Println("I have a lock!")
// Sleep and check the remaining TTL.
time.Sleep(50 * time.Millisecond)
if ttl, err := lock.TTL(); err != nil {
log.Fatalln(err)
} else if ttl > 0 {
fmt.Println("Yay, I still have my lock!")
}
// Extend my lock.
if err := lock.Refresh(100*time.Millisecond, nil); err != nil {
log.Fatalln(err)
}
// Sleep a little longer, then check.
time.Sleep(100 * time.Millisecond)
if ttl, err := lock.TTL(); err != nil {
log.Fatalln(err)
} else if ttl == 0 {
fmt.Println("Now, my lock has expired!")
}
// Output:
// I have a lock!
// Yay, I still have my lock!
// Now, my lock has expired!
}