go,redis 实现分布式锁

1.初始化redis

type RedisConf struct {
	Hostname     string
	Hostport     string
	Password     string
	MaxIdleConns int
	MaxOpenConns int
	MaxLifeTime  int
}

func GetPool(conf *RedisConf) *redis.Pool {
	return &redis.Pool{
		Dial: func() (conn redis.Conn, err error) {
			c, err := redis.Dial("tcp", conf.Hostname+":"+conf.Hostport,
				redis.DialConnectTimeout(time.Second*3),
				redis.DialReadTimeout(time.Second*3),
				redis.DialWriteTimeout(time.Second*3),
			)
			if err != nil {
				return nil, err
			}
			if conf.Password != "" { // 有可能没有密码
				if _, err := c.Do("AUTH", conf.Password); err != nil {
					c.Close()
					return nil, err
				}
			}
			return c, nil
		},
		MaxIdle:     conf.MaxIdleConns,                             // 最初的连接数量
		MaxActive:   conf.MaxOpenConns,                             // 连接池最大连接数量,不确定可以用0(0表示自动定义,按需分配)
		IdleTimeout: time.Duration(conf.MaxLifeTime) * time.Second, // 连接关闭时间100秒(100秒不使用将关闭)
		Wait:        true,                                          // 超过最大连接,是报错,还是等待
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			if time.Since(t) < time.Minute {
				return nil
			}

			_, err := c.Do("PING")
			return err
		},
	}
}

func NewRedis(conf *RedisConf) *goRedis.Client {
	newClient := goRedis.NewClient(&goRedis.Options{
		Addr:            fmt.Sprintf("%s:%s", conf.Hostname, conf.Hostport),
		Password:        conf.Password,
		DialTimeout:     time.Second * 3,
		ReadTimeout:     time.Second * 3,
		WriteTimeout:    time.Second * 3,
		PoolSize:        conf.MaxIdleConns,
		MaxActiveConns:  conf.MaxOpenConns,
		ConnMaxIdleTime: time.Duration(conf.MaxLifeTime) * time.Second,
	})
	return newClient
}

2.分布式锁

func RedLock(redPool *redis.Pool, Key string, exprTime time.Duration) (*redsync.Mutex, error) {
	r := redsync.New(redigo.NewPool(redPool))
	mutex := r.NewMutex(Key, redsync.WithExpiry(exprTime), redsync.WithTries(32))

	if err := mutex.Lock(); err != nil {
		log.Errorf("RedLock err: %s", err.Error())
		return nil, err
	}
	fmt.Println(fmt.Sprintf("accountLock success Key:%s", Key))
	return mutex, nil
}

func RedUnLock(mutex *redsync.Mutex) {
	i := 0
loop:
	unlock, err := mutex.Unlock()
	if err != nil || !unlock {
		i += 1
		if i <= 2 {
			time.Sleep(200 * time.Millisecond)
			goto loop
		}
		log.Errorf("redsync.SetMutex err: %v, name:%v", err, mutex.Name())
		return
	}
}
posted @ 2025-02-19 15:50  9912  阅读(21)  评论(0)    收藏  举报