redislock

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 24, 2019 License: Apache-2.0 Imports: 9 Imported by: 651

README

redislock

Build Status GoDoc Go Report Card License

Simplified distributed locking implementation using Redis. For more information, please see examples.

Examples

import (
  "fmt"
  "time"

  "github.com/bsm/redislock"
  "github.com/go-redis/redis"
)

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(client)

	// Try to obtain lock.
	lock, err := locker.Lock("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!")
	}

}

Documentation

Full documentation is available on GoDoc

Documentation

Overview

Example
package main

import (
	"fmt"
	"log"
	"time"

	"github.com/bsm/redislock"
	"github.com/go-redis/redis"
)

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(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

View Source
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

func (c *Client) Obtain(key string, ttl time.Duration, opt *Options) (*Lock, error)

Obtain tries to otain a new lock using a key with the given TTL. May return ErrNotObtained if not successful.

type Lock

type Lock struct {
	// contains filtered or unexported fields
}

Lock represents an ontained, distributed lock.

func Obtain

func Obtain(client RedisClient, key string, ttl time.Duration, opt *Options) (*Lock, error)

Obtain is a short-cut for New(...).Obtain(...).

func (*Lock) Key

func (l *Lock) Key() string

Key returns the redis key used by the lock.

func (*Lock) Metadata

func (l *Lock) Metadata() string

Metadata returns the metadata of the lock.

func (*Lock) Refresh

func (l *Lock) Refresh(ttl time.Duration, opt *Options) error

Refresh extends the lock with a new TTL. May return ErrNotObtained if refresh is unsuccessful.

func (*Lock) Release

func (l *Lock) Release() error

Release manually releases the lock. May return ErrLockNotHeld.

func (*Lock) TTL

func (l *Lock) TTL() (time.Duration, error)

TTL returns the remaining time-to-live. Returns 0 if the lock has expired.

func (*Lock) Token

func (l *Lock) Token() string

Token returns the token value set by the lock.

type Options

type Options struct {
	// The number of time the acquisition of a lock will be retried.
	// Default: 0 = do not retry
	RetryCount int

	// RetryBackoff is the amount of time to wait between retries.
	// Default: 100ms
	RetryBackoff time.Duration

	// Metadata string is appended to the lock token.
	Metadata string

	// Optional context for Obtain timeout and cancellation control.
	Context context.Context
}

Options describe the options for the lock

type RedisClient

type RedisClient interface {
	SetNX(key string, value interface{}, expiration time.Duration) *redis.BoolCmd
	Eval(script string, keys []string, args ...interface{}) *redis.Cmd
	EvalSha(sha1 string, keys []string, args ...interface{}) *redis.Cmd
	ScriptExists(scripts ...string) *redis.BoolSliceCmd
	ScriptLoad(script string) *redis.StringCmd
}

RedisClient is a minimal client interface.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL