IT人生

  • 首页
  • 归档
  • kafka
  • Java
  • Spring
  • Golang
  • SQL
  • Spark
  • ElasticSearch
  • 关于

  • 搜索
Phoenix HBase Kudu ElasticSearch Spring 数据结构 操作系统 Kettle Azkaban Sqoop Hive Yarn Redis Mybatis Impala Cloudera 大数据 HDFS mycat shell Linux 架构 并发 mysql sql golang java 工具 spark kafka 人生

golang系列(二)基于Redis的分布式锁

发表于 2019-03-09 | 分类于 golang | 0 | 阅读次数 2204
  1. golang系列(一)在Beego中存取Redis
  2. golang系列(二)基于Redis的分布式锁
  3. golang系列(三)在golang中使用kafka
  4. golang系列(四)在golang中使用gorm
  5. golang系列(五)常见的陷阱和错误
package redis_lok

import (
	"fmt"
	"github.com/astaxie/beego"
	"github.com/gomodule/redigo/redis"
	"riskcontrol/logger"
	"time"
)

const (
	default_timeout  = 60
	default_redis_pool_max_idle  = 10
	default_redis_pool_max_active = 20
)


var redisClient *redis.Pool


type Lock struct {
	resource string
	token    string
	timeout  int
}

func init()  {
	redisHost := beego.AppConfig.String("Redis::Address")
	dataBase,err := beego.AppConfig.Int("Redis::DataBase")
	if err != nil{
		logger.Logger.Error("redis database config error",err)
		panic("redis database config error")
	}
	password := beego.AppConfig.String("Redis::Password")

	// 建立连接池
	redisClient = &redis.Pool{
		MaxIdle:     default_redis_pool_max_idle,
		MaxActive:   default_redis_pool_max_active,
		IdleTimeout: default_timeout * time.Second,
		Wait:        true,
		Dial: func() (redis.Conn, error) {
			con, err := redis.Dial("tcp", redisHost,
				redis.DialPassword(password),
				redis.DialDatabase(dataBase),
				redis.DialConnectTimeout(default_timeout*time.Second),
				redis.DialReadTimeout(default_timeout*time.Second),
				redis.DialWriteTimeout(default_timeout*time.Second))
			if err != nil {
				return nil, err
			}
			return con, nil
		},
	}
}

func (lock *Lock) tryLock() (ok bool, err error) {
	_, err = redis.String(redisClient.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) UnlockDeferDefault() (err error) {
	time.Sleep(time.Duration(default_timeout) * time.Second)
	_, err = redisClient.Get().Do("del", lock.key())
	return
}

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

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

func (lock *Lock) AddTimeout(ex_time int64) (ok bool, err error) {
	ttl_time, err := redis.Int64(redisClient.Get().Do("TTL", lock.key()))
	fmt.Println(ttl_time)
	if err != nil {
		logger.Logger.Error("redis get failed:", err)
	}
	if ttl_time > 0 {
		fmt.Println(11)
		_, err := redis.String(redisClient.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 TryLock(resource string, token string) (lock *Lock, ok bool, err error) {
	return TryLockWithTimeout(resource, token, default_timeout)
}

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

	ok, err = lock.tryLock()

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

	return
}


func demo() {
	logger.Logger.Info("start")

	lock, ok, err := TryLock( "test_key", "test_value")
	if err != nil {
		logger.Logger.Error("Error while attempting lock")
	}
	if !ok {
		logger.Logger.Error("Lock failed")
	}

	defer lock.UnlockDeferDefault()
}

  • 本文作者: Randy
  • 本文链接: http://www.itrensheng.com/archives/golangredis
  • 版权声明: 本博客所有文章除特别声明外,均采用CC BY-NC-SA 3.0 许可协议。转载请注明出处!
# Phoenix # HBase # Kudu # ElasticSearch # Spring # 数据结构 # 操作系统 # Kettle # Azkaban # Sqoop # Hive # Yarn # Redis # Mybatis # Impala # Cloudera # 大数据 # HDFS # mycat # shell # Linux # 架构 # 并发 # mysql # sql # golang # java # 工具 # spark # kafka # 人生
golang系列(一)在Beego中存取Redis
golang系列(三)在golang中使用kafka
  • 文章目录
  • 站点概览
Randy

Randy

技术可以暂时落后,但任何时候都要有上进的信念

80 日志
27 分类
31 标签
RSS
Github E-mail
Creative Commons
© 2021 备案号:沪ICP备19020689号-1
Randy的个人网站