您的位置:首页 > 数据库 > Redis

golang redis连接池式分布式锁小小的封装

2019-08-14 16:14 1546 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/weixin_39998006/article/details/99579473

摘要:把redis加锁方法单独抽离出去放入一个公共方法,暂未做数据类型断言

helper redisLock 文件

package helper

import (
"fmt"
"github.com/garyburd/redigo/redis"
"github.com/prometheus/common/log"
)

type Lock struct {
resource string
token    int64
conn     redis.Pool
timeout  int
}

func (lock *Lock) tryLock() (ok bool, err error) {
_, err = redis.String(lock.conn.Get().Do("SET", lock.key(), lock.token, "EX", int(lock.timeout), "NX"))
if err == redis.ErrNil {
// The lock was not successful, it already exists.
return false, nil
}
if err != nil {
return false, err
}
return true, nil
}

func (lock *Lock) Unlock() (err error) {
_, err = lock.conn.Get().Do("del", lock.key())
return
}

func (lock *Lock) Close() (err error) {
if lock != nil {
lock.conn.Close()
}
return
}

func (lock *Lock) key() string {
return fmt.Sprintf("redislock:%s", lock.resource)
}

func (lock *Lock) AddTimeout(ex_time int64) (ok bool, err error) {
ttl_time, err := redis.Int64(lock.conn.Get().Do("TTL", lock.key()))
fmt.Println(ttl_time)
if err != nil {
log.Fatal("redis get failed:", err)
}
if ttl_time > 0 {
fmt.Println(11)
_, err := redis.String(lock.conn.Get().Do("SET", lock.key(), lock.token, "EX", int(ttl_time+ex_time)))
if err == redis.ErrNil {
return false, nil
}
if err != nil {
return false, err
}
}
return false, nil
}
func (lock *Lock) Get(key string) int64 {
sum, err := redis.Int64(lock.conn.Get().Do("TTL", lock.resource))
if err != nil {
log.Fatal("redis get failed:", err)
}
return sum
}

func TryLockWithTimeout(conn redis.Pool, resource string, token int64, timeout int) (lock *Lock, ok bool, err error) {
lock = &Lock{resource, token, conn, timeout}

ok, err = lock.tryLock()

if !ok || err != nil {
lock = nil
}

return
}
func TryLock(conn redis.Pool, key string, value int64, DefaulTimeout int) (lock *Lock, ok bool, err error) {
return TryLockWithTimeout(conn, key, value, DefaulTimeout)
}

调用(有一些无用import我懒得删了,复制粘贴自行删除)

package main

import (
"apitest/helper"
"context"
"flag"
"fmt"
"github.com/garyburd/redigo/redis"
"github.com/panjf2000/ants"
"github.com/rpcx-ecosystem/rpcx-examples3"
"github.com/smallnest/rpcx/client"
"log"
"net/http"
"time"
)

var redisPool = &redis.Pool{
MaxIdle:     30,
MaxActive:   1000,
IdleTimeout: 30 * time.Second,
Dial: func() (conn redis.Conn, err error) {
//RedisHost := "127.0.0.1:6379" //连接地址
//RedisPassword := ""           //连接密码
return redis.Dial("tcp", "127.0.0.1:32769")
},
}

func main() {
//redisPool.Close()
rs := redisPool
//defer rs.Close()
res, ok, err := helper.TryLock(*rs, "key", 0, 12)
//res, ok, err := TryLock(*rs, "key", 0, 12)
if err != nil {
panic(err)
}
if ok {
fmt.Println("加锁成功")
res.Unlock()
} else {
fmt.Println("加锁失败")
}
res.Close()

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: