Skip to content

everfore/rddlock

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

28 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rddlock

redis distributed lock

redis 分布式锁实现, 原理:redis 分布式锁实现

lock的超时时间:timeout_ms

Usage

Lock & UnLock

lockkey := "lock-key"
timeout_ms := 3000

locked, ex := rddlock.Lock(rds, lockkey, timeout_ms)
defer reelock.UnLock(rds, lockkey, ex)

LockRetry

重试retry_times次,尝试获得锁

retry_times := 10
locked, ex := reelock.LockRetry(rds, lockkey, timeout_ms, retry_times) // get lock by retry
defer reelock.UnLock(rds, lockkey, ex)

UnLockUnsafe

locked, _ := rddlock.Lock(rds, lockkey, timeout_ms)
defer reelock.UnLockUnsafe(rds, lockkey)

UnLockSafe

预留安全时间,释放锁。

locked, _ := rddlock.Lock(rds, lockkey, timeout_ms)
safeDelTime_ms := 40
defer reelock.UnLockSafe(rds, lockkey, safeDelTime_ms)

SyncDo

err := SyncDo(rds, lockkey, timeout_ms, func(timeout chan bool) chan bool {
		ret := make(chan bool, 1)
		go func() {
			fmt.Println("doing...")
			// TODO SOMETHING
			select {
			case <-timeout:
				// do the rollback
				break
			case ret <- true:
				fmt.Println("success end.")
			}
		}()
		return ret
	})

Example

package main

import (
	"fmt"

	"github.com/everfore/rddlock"
	"gopkg.in/ezbuy/redis-orm.v1/orm"
	redis "gopkg.in/redis.v5"
)

func main() {
	// rds, err := orm.NewRedisClient("localhost", 32768, "", 0)
	rds, err := orm.NewRedisClusterClient(&redis.ClusterOptions{
		Addrs: []string{"XXX", "XXX", "XXX"},
	})
	if err != nil {
		panic(err)
	}

	lock_key := "lock-key"

	locked, ex := rddlock.Lock(rds, lock_key, 5)
	if locked {
		fmt.Printf("LOCK %s: %+v\n", lock_key, locked)
		unlocked := rddlock.UnLock(rds, lock_key, ex)
		if unlocked {
			fmt.Printf("UNLOCK %s: %+v\n", lock_key, unlocked)
		} else {
			unlocked = rddlock.UnLockUnsafe(rds, lock_key)
			fmt.Printf("UNLOCK-UNSAFE %s: %+v\n", lock_key, unlocked)
		}
	}

	// retry lock

	// 1. lock the key first
	locked, _ = rddlock.Lock(rds, lock_key, 5)
	fmt.Printf("FIRST step, LOCK %s:%+v\n", lock_key, locked)
	// 2. retry to lock the locked key
	locked, _ = rddlock.LockRetry(rds, lock_key, 100, 100)
	fmt.Printf("SECOND step, LOCK-RETRY %s:%+v\n", lock_key, locked)
}

// Output
// LOCK lock-key: true
// UNLOCK lock-key: true
// FIRST step, LOCK lock-key:true
// SECOND step, LOCK-RETRY lock-key:true

test

success:200, avg:1.1074123 ms
failed:0, avg:NaN ms
--- PASS: TestLockTime (10.59s)

#local-redis
=== RUN   TestLockRetryTime
success:200, avg:1.1741205 ms
failed:0, avg:NaN ms
--- PASS: TestLockRetryTime (10.58s)

#uat-redis
=== RUN   TestLockRetryTime
success:200, avg:12.572702 ms
failed:0, avg:NaN ms
--- PASS: TestLockRetryTime (10.59s)