Golang - Redis 锁

Redis 锁

package main

import (
	"errors"
	"fmt"
	"github.com/garyburd/redigo/redis"
	"time"
)

var RedisPool = &redis.Pool{
	MaxIdle:     1,
	MaxActive:   10,
	IdleTimeout: 180 * time.Second,
	Dial: func() (redis.Conn, error) {
		c, err := redis.Dial("tcp", "192.168.200.130:6379")
		if err != nil {
			return nil, err
		}
		// 选择db
		c.Do("SELECT", 0)
		return c, nil
	},
}

type Locker struct {
	Key    string
	Error  error
}

func Lock(key string) (locker *Locker) {
	locker = &Locker{Key: key}

	redisConn := RedisPool.Get()
	reply, _ := redis.String(redisConn.Do("SET", key, 1, "EX", 60, "NX"))
	redisConn.Close()

	if reply != "OK" {
		locker.Error = errors.New("locker failed.")
	}
	return
}

func TryLock(key string, timeout time.Duration) (locker *Locker) {
	locker = &Locker{Key: key}

	start := time.Now()
	for time.Now().Sub(start) < timeout {
		redisConn := RedisPool.Get()
		reply, _ := redis.String(redisConn.Do("SET", key, 1, "EX", 60, "NX"))
		redisConn.Close()
		
		if reply == "OK" {
			return
		}

		time.Sleep(time.Duration(200) * time.Millisecond)
	}

	locker.Error = errors.New("locker timeout.")
	return
}

func (lock *Locker) Close() {
	if lock.Error == nil {
		redisConn := RedisPool.Get()
		redisConn.Do("DEL", lock.Key)
		redisConn.Close()
	}
}

func main() {
	locker := TryLock("a", 5*time.Second)

	if locker.Error != nil {
		fmt.Print(locker.Error)
	}

	defer locker.Close()
}

你可能感兴趣的:(Golang)