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

摘要:把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()

}

你可能感兴趣的:(goalng,缓存)