Documentation
¶
Overview ¶
Example ¶
// 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(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!
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNotObtained is returned when a lock cannot be obtained. ErrNotObtained = errors.New("redislock: not obtained") // ErrLockNotHeld is returned when trying to release an inactive lock. ErrLockNotHeld = errors.New("redislock: lock not held") )
Functions ¶
This section is empty.
Types ¶
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client wraps a redis client.
func New ¶
func New(client RedisClient) *Client
New creates a new Client instance with a custom namespace.
func (*Client) Obtain ¶
Obtain tries to obtain a new lock using a key with the given TTL. May return ErrNotObtained if not successful.
Example (CustomDeadline) ¶
client := redis.NewClient(&redis.Options{Network: "tcp", Addr: "127.0.0.1:6379"})
defer client.Close()
locker := redislock.New(client)
// Retry every 500ms, for up-to a minute
backoff := redislock.LinearBackoff(500 * time.Millisecond)
ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(time.Minute))
defer cancel()
// Obtain lock with retry + custom deadline
lock, err := locker.Obtain("my-key", time.Second, &redislock.Options{
RetryStrategy: backoff,
Context: ctx,
})
if err == redislock.ErrNotObtained {
fmt.Println("Could not obtain lock!")
} else if err != nil {
log.Fatalln(err)
}
defer lock.Release()
fmt.Println("I have a lock!")
Example (Retry) ¶
client := redis.NewClient(&redis.Options{Network: "tcp", Addr: "127.0.0.1:6379"})
defer client.Close()
locker := redislock.New(client)
// Retry every 100ms, for up-to 3x
backoff := redislock.LimitRetry(redislock.LinearBackoff(100*time.Millisecond), 3)
// Obtain lock with retry
lock, err := locker.Obtain("my-key", time.Second, &redislock.Options{
RetryStrategy: backoff,
})
if err == redislock.ErrNotObtained {
fmt.Println("Could not obtain lock!")
} else if err != nil {
log.Fatalln(err)
}
defer lock.Release()
fmt.Println("I have a lock!")
type Lock ¶
type Lock struct {
// contains filtered or unexported fields
}
Lock represents an obtained, distributed lock.
func (*Lock) Refresh ¶
Refresh extends the lock with a new TTL. May return ErrNotObtained if refresh is unsuccessful.
type Options ¶
type Options struct {
// RetryStrategy allows to customise the lock retry strategy.
// Default: do not retry
RetryStrategy RetryStrategy
// Metadata string is appended to the lock token.
Metadata string
// Context provides an optional context for timeout and cancellation control.
// If requested, Obtain will by default retry until the TTL exires. This
// behaviour can be tweaked with a custom context deadline.
Context context.Context
}
Options describe the options for the lock
type RedisClient ¶
type RedisClient interface {
SetNX(ctx context.Context, key string, value interface{}, expiration time.Duration) *redis.BoolCmd
Eval(ctx context.Context, script string, keys []string, args ...interface{}) *redis.Cmd
EvalSha(ctx context.Context, sha1 string, keys []string, args ...interface{}) *redis.Cmd
ScriptExists(ctx context.Context, scripts ...string) *redis.BoolSliceCmd
ScriptLoad(ctx context.Context, script string) *redis.StringCmd
}
RedisClient is a minimal client interface.
type RetryStrategy ¶ added in v0.4.0
type RetryStrategy interface {
// NextBackoff returns the next backoff duration.
NextBackoff() time.Duration
}
RetryStrategy allows to customise the lock retry strategy.
func ExponentialBackoff ¶ added in v0.4.0
func ExponentialBackoff(min, max time.Duration) RetryStrategy
ExponentialBackoff strategy is an optimization strategy with a retry time of 2**n milliseconds (n means number of times). You can set a minimum and maximum value, the recommended minimum value is not less than 16ms.
func LimitRetry ¶ added in v0.4.0
func LimitRetry(s RetryStrategy, max int) RetryStrategy
LimitRetry limits the number of retries to max attempts.
func LinearBackoff ¶ added in v0.4.0
func LinearBackoff(backoff time.Duration) RetryStrategy
LinearBackoff allows retries regularly with customized intervals

