Simplified distributed locking implementation using Redis, forked from bsm/redislock. For more information, please see examples.
import (
"context"
"fmt"
"log"
"time"
"github.com/go-redis/redis/v8"
"github.com/someonegg/redislock"
)
type redisClientV8 struct {
o *redis.Client
}
func (c redisClientV8) Get(ctx context.Context, key string) (string, error) {
return c.o.Get(ctx, key).Result()
}
func (c redisClientV8) Eval(ctx context.Context, script string, keys []string, args ...interface{}) (interface{}, error) {
return c.o.Eval(ctx, script, keys, args...).Result()
}
func (c redisClientV8) EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) (interface{}, error) {
return c.o.EvalSha(ctx, sha1, keys, args...).Result()
}
func main() {
// Connect to redis.
client := redis.NewClient(&redis.Options{
Network: "tcp",
Addr: "127.0.0.1:6379",
})
defer client.Close()
// Create a new lock client.
locker := redislock.New(redisClientV8{client})
ctx := context.Background()
// Try to obtain lock.
lock, err := locker.Obtain(ctx, "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(ctx)
fmt.Println("I have a lock!")
// Sleep and check the remaining TTL.
time.Sleep(50 * time.Millisecond)
if ttl, err := lock.TTL(ctx); err != nil {
log.Fatalln(err)
} else if ttl > 0 {
fmt.Println("Yay, I still have my lock!")
}
// Extend my lock.
if err := lock.Refresh(ctx, 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(ctx); err != nil {
log.Fatalln(err)
} else if ttl == 0 {
fmt.Println("Now, my lock has expired!")
}
}Full documentation is available on GoDoc