rueidislock

package
v0.0.0-...-c14f4f2 Latest Latest
Warning

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

Go to latest
Published: Nov 13, 2022 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/rueian/rueidis"
	"github.com/rueian/rueidis/rueidislock"
)

func main() {
	locker, err := rueidislock.NewLocker(rueidislock.LockerOption{
		ClientOption: rueidis.ClientOption{InitAddress: []string{"node1:6379", "node2:6380", "node3:6379"}},
		KeyMajority:  2,
	})
	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 if the KeyMajority is not held anymore.
  • The waiting Locker.WithContext will retry again if the lock is released by someone.

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.
  2. If the KeyMajority is satisfied within the KeyValidity duration, the invocation is successful and a ctx is returned.
  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.

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)
	// 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 {
	// ClientOption is passed to rueidis.NewClient or LockerOption.ClientBuilder to build a rueidis.Client
	ClientOption rueidis.ClientOption
	// 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
	// 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
}

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