godisson

package module
v0.0.6 Latest Latest
Warning

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

Go to latest
Published: Jun 22, 2022 License: Apache-2.0 Imports: 13 Imported by: 1

README

go-redisson

a Redisson like distributed locking implementation using Redis.

Explanation

中文

Installation

go get github.com/cheerego/go-redisson

Support Lock Category

  • Mutex Example

    • Exclusive Lock (X Lock).
    • use it like std package sync.Mutex.
    • not a reentrant lock that can't lock twice in a same goroutine.
  • RLock Example

    • Exclusive Reentrant Lock.
    • use it like java redisson.
    • a reentrant lock that can lock many times in a same goroutine.

Features

  • tryLock,if waitTime > 0, wait waitTime milliseconds to try to obtain lock by while true and redis pub sub.
  • watchdog, if leaseTime = -1, start a time.Ticker(defaultWatchDogTime / 3) to renew lock expiration time.

Options

WatchDogTimeout

g := godisson.NewGodisson(rdb, godisson.WithWatchDogTimeout(30*time.Second))

Examples

Mutex

package main

import (
  "github.com/cheerego/go-redisson"
  "github.com/go-redis/redis/v8"
  "github.com/pkg/errors"
  "log"
  "time"
)

func main() {

  // create redis client
  rdb := redis.NewClient(&redis.Options{
    Addr:     "localhost:6379",
    Password: "", // no password set
    DB:       0,  // use default DB
  })
  defer rdb.Close()

  g := godisson.NewGodisson(rdb, godisson.WithWatchDogTimeout(30*time.Second))

  test1(g)
  test2(g)
}

// can't obtain lock in a same goroutine
func test1(g *godisson.Godisson) {
  m1 := g.NewMutex("godisson")
  m2 := g.NewMutex("godisson")

  err := m1.TryLock(-1, 20000)
  if errors.Is(err, godisson.ErrLockNotObtained) {
    log.Println("can't obtained lock")
  } else if err != nil {
    log.Fatalln(err)
  }
  defer m1.Unlock()

  // because waitTime = -1, waitTime < 0, try once, will return ErrLockNotObtained
  err = m2.TryLock(-1, 20000)
  if errors.Is(err, godisson.ErrLockNotObtained) {
    log.Println("m2 must not obtained lock")
  } else if err != nil {
    log.Fatalln(err)
  }
  time.Sleep(10 * time.Second)
}

func test2(g *godisson.Godisson) {
  m1 := g.NewMutex("godisson")
  m2 := g.NewMutex("godisson")

  go func() {
    err := m1.TryLock(-1, 20000)
    if errors.Is(err, godisson.ErrLockNotObtained) {
      log.Println("can't obtained lock")
    } else if err != nil {
      log.Fatalln(err)
    }
    time.Sleep(10 * time.Second)
    m1.Unlock()
  }()

  // waitTime > 0, after 10 milliseconds will obtain the lock
  go func() {
    time.Sleep(1 * time.Second)

    err := m2.TryLock(15000, 20000)
    if errors.Is(err, godisson.ErrLockNotObtained) {
      log.Println("m2 must not obtained lock")
    } else if err != nil {
      log.Fatalln(err)
    }
    time.Sleep(10 * time.Second)

    m2.Unlock()
  }()
  time.Sleep(20 * time.Second)

}


RLock

package main

import (
  "github.com/cheerego/go-redisson"
  "github.com/go-redis/redis/v8"
  "log"
  "time"
)

func main() {

  // create redis client
  rdb := redis.NewClient(&redis.Options{
    Addr:     "localhost:6379",
    Password: "", // no password set
    DB:       0,  // use default DB
  })
  defer rdb.Close()

  g := godisson.NewGodisson(rdb, godisson.WithWatchDogTimeout(30*time.Second))

  // lock with watchdog without retry
  lock := g.NewRLock("godisson")

  err := lock.Lock()
  if err == godisson.ErrLockNotObtained {
    log.Println("Could not obtain lock")
  } else if err != nil {
    log.Fatalln(err)
  }
  defer lock.Unlock()

  // lock with retry、watchdog
  // leaseTime value is -1, enable watchdog
  lock2 := g.NewRLock("godission-try-watchdog")

  err = lock2.TryLock(20000, -1)
  if err == godisson.ErrLockNotObtained {
    log.Println("Could not obtain lock")
  } else if err != nil {
    log.Fatalln(err)
  }
  time.Sleep(10 * time.Second)
  defer lock.Unlock()
}

Documentation

Index

Constants

View Source
const READ_UNLOCK_MESSAGE int64 = 1
View Source
const UNLOCK_MESSAGE int64 = 0

Variables

View Source
var DefaultWatchDogTimeout = 30 * time.Second
View Source
var ErrLockNotObtained = errors.New("ErrLockNotObtained")

Functions

This section is empty.

Types

type Godisson

type Godisson struct {

	// key uuid:key, value entry
	RenewMap cmap.ConcurrentMap
	// contains filtered or unexported fields
}

func NewGodisson

func NewGodisson(redisClient *redis.Client, opts ...OptionFunc) *Godisson

func (*Godisson) NewMutex

func (g *Godisson) NewMutex(key string) *Mutex

func (*Godisson) NewRLock

func (g *Godisson) NewRLock(key string) *RLock

type Locker

type Locker interface {
	TryLock(waitTime int64, leaseTime int64) error
	Unlock() (int64, error)
}

type Mutex

type Mutex struct {
	Key string
	// contains filtered or unexported fields
}

func (*Mutex) TryLock

func (m *Mutex) TryLock(waitTime int64, leaseTime int64) error

func (*Mutex) Unlock

func (m *Mutex) Unlock() (int64, error)

type OptionFunc

type OptionFunc func(g *Godisson)

func WithWatchDogTimeout

func WithWatchDogTimeout(t time.Duration) OptionFunc

type RLock

type RLock struct {
	Key string
	// contains filtered or unexported fields
}

func (*RLock) Lock

func (r *RLock) Lock() error

func (*RLock) TryLock

func (r *RLock) TryLock(waitTime int64, leaseTime int64) error

TryLock try to obtain lock waitTime, Millisecond leaseTime, Millisecond, -1 enable watchdog

func (*RLock) Unlock

func (r *RLock) Unlock() (int64, error)

type RenewEntry

type RenewEntry struct {
	sync.Mutex
	// contains filtered or unexported fields
}

func NewRenewEntry

func NewRenewEntry() *RenewEntry

Directories

Path Synopsis
examples

Jump to

Keyboard shortcuts

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