GO 实现REDIS分布式原子锁的功能

package redis

import (
	"errors"
	"fmt"

	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/util/gconv"
	"github.com/gomodule/redigo/redis"
)

const (
	lockScript   = `return redis.call('SET', KEYS[1], ARGV[1], 'NX', 'EX', ARGV[2])`
	unlockScript = `
		if redis.call("get",KEYS[1]) == ARGV[1] then
		    return redis.call("del",KEYS[1])
		else
		    return 0
		end
	`
)

func Lock(key, value string, timeoutMs int) (bool, error) {
	r := g.Redis().Conn()
	defer r.Close()
	cmd := redis.NewScript(1, lockScript)
	if res, err := cmd.Do(r, key, value, timeoutMs); err != nil {
		//fmt.Printf("加锁失败, k:%v v:%v", key, value)
		return false, err
	} else {
		//fmt.Printf("加锁成功, k:%v v:%v res %v \n", key, value, res)
		return gconv.String(res) == "OK", nil
	}
}

func Unlock(key, value string) error {
	r := g.Redis().Conn()
	defer r.Close()
	cmd := redis.NewScript(1, unlockScript)
	if res, err := redis.Int(cmd.Do(r, key, value)); err != nil {
		return err
	} else if res != 1 {
		msg := fmt.Sprintf("解锁失败, key:%v 或者 v:%v 错误", key, value)
		return errors.New(msg)
	}
	return nil
}

由于我当时用的是GF的框架所以REDIS也是用了GF上面提供的驱动。如果你用其它的可以改一下就可以使用了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值