Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

redisLock

  • 这是一款基于redis的分布式锁(支持单节点和集群)
  • 支持看门狗进行锁过期时间的自动延续
  • 支持用户自定义锁相关配置:锁过期时间、是否启动看门狗、是否阻塞模式、阻塞等锁时间等

How to use it?

1.download

go get -u github.com/TDroyal/redislock

2.example

package redislock_test

import (
	"context"
	"sync"
	"testing"
	"time"

	"github.com/TDroyal/redislock"
)

func TestNonBlockLock(t *testing.T) {
	// node1
	c1 := redislock.NewClient("tcp", "xxxxxx:xxxx", "yyyyyy", redislock.WithMaxActive(20), redislock.WithIdleTimeoutSeconds(10))
	var locker1 redislock.RedisLock = redislock.NewRedisDistributedLock("non_block_test_key", c1, redislock.WithExpireSeconds(3))

	// node2
	c2 := redislock.NewClient("tcp", "xxxxxx:xxxx", "yyyyyy", redislock.WithMaxActive(20), redislock.WithIdleTimeoutSeconds(10))
	var locker2 redislock.RedisLock = redislock.NewRedisDistributedLock("non_block_test_key", c2, redislock.WithExpireSeconds(3))

	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		defer wg.Done()
		err := locker1.Lock(context.Background())
		// if err == nil {
		// 	locker1.UnLock(context.Background())
		// }
		t.Log(err) // <nil>
	}()

	go func() {
		time.Sleep(time.Millisecond)
		defer wg.Done()
		err := locker2.Lock(context.Background())
		if err == nil {
			locker2.UnLock(context.Background())
		}
		t.Log(err) // lock is acquired by others
	}()

	wg.Wait()

}

func TestBlockLock(t *testing.T) {
	// node1
	c1 := redislock.NewClient("tcp", "xxxxxx:xxxx", "yyyyyy", redislock.WithMaxActive(20), redislock.WithIdleTimeoutSeconds(10))
	locker1 := redislock.NewRedisDistributedLock("block_test_key", c1, redislock.WithExpireSeconds(3))

	// node2
	c2 := redislock.NewClient("tcp", "xxxxxx:xxxx", "yyyyyy", redislock.WithMaxActive(20), redislock.WithIdleTimeoutSeconds(10))
	locker2 := redislock.NewRedisDistributedLock("block_test_key", c2, redislock.WithBlock(), redislock.WithBlockingSeconds(5), redislock.WithWatchDogMode(), redislock.WithExpireSeconds(15))

	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		defer wg.Done()
		err := locker1.Lock(context.Background())
		// if err == nil {
		// 	locker1.UnLock(context.Background())
		// }
		t.Logf("time: %v, error: %v", time.Now().Format("2006-01-02 15:04:05"), err) // time: 2026-05-21 15:22:24, error: <nil>
	}()

	go func() {
		time.Sleep(time.Millisecond * 10)
		defer wg.Done()
		err := locker2.Lock(context.Background())
		if err == nil {
			locker2.UnLock(context.Background())
		}
		t.Logf("time: %v, error: %v", time.Now().Format("2006-01-02 15:04:05"), err) // time: 2026-05-21 15:22:27, error: <nil>
	}()

	wg.Wait()
}

func TestRedLock(t *testing.T) {
	confs := []*redislock.SingleRedisNodeConf{
		{
			Network:  "tcp",
			Address:  "xxxxxx:xxxx",
			Password: "yyyyyy",
			RedisOpts: []redislock.RedisOption{
				redislock.WithMaxActive(20),
				redislock.WithIdleTimeoutSeconds(10),
			},
		},
		{
			Network:  "tcp",
			Address:  "xxxxxx:xxxx",
			Password: "yyyyyy",
			RedisOpts: []redislock.RedisOption{
				redislock.WithMaxActive(20),
				redislock.WithIdleTimeoutSeconds(10),
			},
		},
		{
			Network:  "tcp",
			Address:  "xxxxxx:xxxx",
			Password: "yyyyyy",
			RedisOpts: []redislock.RedisOption{
				redislock.WithMaxActive(20),
				redislock.WithIdleTimeoutSeconds(10),
			},
		},
	}
	// node1
	// locker1 := redislock.NewRedLock("red_lock", confs, redislock.WithBlock(), redislock.WithBlockingSeconds(5), redislock.WithWatchDogMode(), redislock.WithExpireSeconds(15))
	locker1 := redislock.NewRedLock("red_lock", confs, redislock.WithExpireSeconds(3))
	// node2
	locker2 := redislock.NewRedLock("red_lock", confs, redislock.WithExpireSeconds(3))

	var wg sync.WaitGroup
	wg.Add(2)
	go func() {
		defer wg.Done()
		err := locker1.Lock(context.Background())
		t.Log(err) // <nil>
	}()

	go func() {
		time.Sleep(time.Millisecond)
		defer wg.Done()
		err := locker2.Lock(context.Background())
		if err == nil {
			locker2.UnLock(context.Background())
		}
		t.Log(err) // lock failed
	}()

	wg.Wait()

}

About

This is a distributed lock based on Redis, supporting both single-node and cluster configurations.

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages