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
}
}