KING 博主等级

一帆风顺 ⛵️⛵️⛵️

Go

redsync(redis分布式锁)

钟晓川
2023-12-11 / 4 点赞 / 1262 阅读

Redsync 是一个基于 Go 的 Redis 实现的分布式锁库,它使用了 Redis 的 SETNX 和 EXPIRE 命令来实现分布式锁。以下是一个简单的示例,展示了如何在 Go 中使用 Redsync 库来实现分布式锁:

Installation

使用 go get 命令安装 Redsync:

go get github.com/go-redsync/redsync/v4

Usage

接下来是一个使用 Redsync 实现分布式锁的示例代码:

// Package redsync
// @Author zhongxc
// @Date 2023/12/11 15:43:00
// @Desc
package main

import (
	"context"
	"fmt"
	"github.com/go-redsync/redsync/v4"
	"github.com/go-redsync/redsync/v4/redis/goredis/v9"
	goredislib "github.com/redis/go-redis/v9"
	"log"
	"time"
)

func main() {
	// 创建客户端实例
	client := goredislib.NewClient(&goredislib.Options{
		Addr:     "127.0.0.1:6379",
		Password: "",
		DB:       0,
	})
	defer func(client *goredislib.Client) {
		_ = client.Close()
	}(client)

	// 创建Redsync实例
	pool := goredis.NewPool(client)
	rs := redsync.New(pool)

	// 创建锁,设置默认过期时间为10秒钟
	mutexname := "my-global-mutex"
	mutex := rs.NewMutex(mutexname, redsync.WithExpiry(10*time.Second))

	ctx, cancelFunc := context.WithCancel(context.Background())
	defer cancelFunc() // 在函数结束时取消context

	// 尝试获取锁
	if err := mutex.Lock(); err != nil {
		log.Fatalln(err)
	}
	log.Println("Successfully acquired lock")

	// 开启一个goroutine进行自动续期
	go func(ctx context.Context) {
		defer fmt.Println("Goroutine stopped")
		ticker := time.NewTicker(6 * time.Second)
		defer ticker.Stop()

		for {
			select {
			case <-ticker.C:
				// 每隔3秒钟(要比锁的过期时间略短),延长锁的过期时间
				if _, err := mutex.Extend(); err != nil {
					log.Println("锁延期失败", err)
				} else {
					log.Println("Lock extended")
				}
			case <-ctx.Done():
				return // 如果context被取消,则结束goroutine
			}
		}
	}(ctx)

	// 完成需要锁的工作
	log.Println("开始处理获取锁后的工作")
	time.Sleep(30 * time.Second)
	log.Println("业务处理成功")

	// 释放锁,以便其他进程或线程可以获得锁
	if ok, err := mutex.Unlock(); !ok || err != nil {
		log.Fatalln("unlock failed", err)
	}
	log.Println("Lock released")
	// time.Sleep(30 * time.Second)
}

相关文档

https://github.com/go-redsync/redsync
https://pkg.go.dev/github.com/go-redsync/redsync#Mutex

4