rueidislock

package
v1.0.25 Latest Latest
Warning

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

Go to latest
Published: Dec 22, 2023 License: Apache-2.0 Imports: 11 Imported by: 0

README

rueidislock

A Redis Distributed Lock Pattern enhanced by Client Side Caching.

package main

import (
	"context"
	"github.com/Datadog/rueidis"
	"github.com/Datadog/rueidis/rueidislock"
)

func main() {
	locker, err := rueidislock.NewLocker(rueidislock.LockerOption{
		ClientOption: rueidis.ClientOption{InitAddress: []string{"node1:6379", "node2:6380", "node3:6379"}},
		KeyMajority:  2, // please make sure that all your `Locker`s share the same KeyMajority
	})
	if err != nil {
		panic(err)
	}
	defer locker.Close()

	// acquire the lock "my_lock"
	ctx, cancel, err := locker.WithContext(context.Background(), "my_lock")
	if err != nil {
		panic(err)
	}

	// "my_lock" is acquired. use the ctx as normal.
	doSomething(ctx)

	// invoke cancel() to release the lock.
	cancel()
}

Features backed by the Redis Client Side Caching

  • The returned ctx will be canceled automatically and immediately once the KeyMajority is not held anymore, for example:
    • Redis down.
    • Related keys has been deleted by other program or administrator.
  • The waiting Locker.WithContext will try acquiring the lock again automatically and immediately once it has been released by someone even from other program.

How it works

When the locker.WithContext is invoked, it will:

  1. Try acquiring 3 keys (given that KeyMajority is 2), which are rueidislock:0:my_lock, rueidislock:1:my_lock and rueidislock:2:my_lock, by sending redis command SET NX PXAT or SET NX PX if FallbackSETPX is set.
  2. If the KeyMajority is satisfied within the KeyValidity duration, the invocation is successful and a ctx is returned as the lock.
  3. If the invocation is not successful, it will wait for client-side caching notification to retry again.
  4. If the invocation is successful, the Locker will extend the ctx validity periodically and also watch client-side caching notification for canceling the ctx if the KeyMajority is not held anymore.
Disable Client Side Caching

Some Redis provider doesn't support client-side caching, ex. Google Cloud Memorystore. You can disable client-side caching by setting ClientOption.DisableCache to true. Please note that when the client-side caching is disabled, rueidislock will only try to re-acquire locks for every ExtendInterval.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var ErrLockerClosed = errors.New("locker closed")

ErrLockerClosed is returned from the Locker.WithContext when the Locker is closed

View Source
var ErrNotLocked = errors.New("not locked")

ErrNotLocked is returned from the Locker.TryWithContext when it fails

Functions

This section is empty.

Types

type Locker

type Locker interface {
	// WithContext acquires a distributed redis lock by name by waiting for it. It may return ErrLockerClosed.
	WithContext(ctx context.Context, name string) (context.Context, context.CancelFunc, error)
	// TryWithContext tries to acquire a distributed redis lock by name without waiting. It may return ErrNotLocked.
	TryWithContext(ctx context.Context, name string) (context.Context, context.CancelFunc, error)
	// Client exports the underlying rueidis.Client
	Client() rueidis.Client
	// Close closes the underlying rueidis.Client
	Close()
}

Locker is the interface of rueidislock

func NewLocker

func NewLocker(option LockerOption) (Locker, error)

NewLocker creates the distributed Locker backed by redis client side caching

type LockerOption

type LockerOption struct {
	// ClientBuilder can be used to modify rueidis.Client used by Locker
	ClientBuilder func(option rueidis.ClientOption) (rueidis.Client, error)
	// KeyPrefix is the prefix of redis key for locks. Default value is "rueidislock".
	KeyPrefix string
	// ClientOption is passed to rueidis.NewClient or LockerOption.ClientBuilder to build a rueidis.Client
	ClientOption rueidis.ClientOption
	// KeyValidity is the validity duration of locks and will be extended periodically by the ExtendInterval. Default value is 5s.
	KeyValidity time.Duration
	// ExtendInterval is the interval to extend KeyValidity. Default value is 1s.
	ExtendInterval time.Duration
	// TryNextAfter is the timeout duration before trying the next redis key for locks. Default value is 20ms.
	TryNextAfter time.Duration
	// KeyMajority is at least how many redis keys in a total of KeyMajority*2-1 should be acquired to be a valid lock.
	// Default value is 2.
	KeyMajority int32
	// NoLoopTracking will use NOLOOP in the CLIENT TRACKING command to avoid unnecessary notifications and thus have better performance.
	// This can only be enabled if all your redis nodes >= 7.0.5. (https://github.com/redis/redis/pull/11052)
	NoLoopTracking bool
	// Use SET PX instead of SET PXAT when acquiring locks to be compatible with Redis < 6.2
	FallbackSETPX bool
}

LockerOption should be passed to NewLocker to construct a Locker

Jump to

Keyboard shortcuts

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