package redis import ( "fmt" "github.com/FZambia/sentinel" "github.com/gomodule/redigo/redis" "github.com/spf13/viper" "strings" "time" ) // sentinel适配器 type SentinelAdapter struct { pool *redis.Pool } // 返回sentinel适配器新实例 func NewSentinelAdapter(nodes []string, masterName string) (IRedisAdapter, error) { opts := []redis.DialOption{redis.DialConnectTimeout(5 * time.Second)} password := viper.GetString("redis.password") if len(strings.TrimSpace(password)) > 0 { opts = append(opts, redis.DialPassword(strings.TrimSpace(password))) } s := &sentinel.Sentinel{ Addrs: nodes, MasterName: masterName, Dial: func(addr string) (redis.Conn, error) { c, err := redis.Dial("tcp", addr, opts...) if err != nil { return nil, err } return c, nil }, } maxIdle := viper.GetInt("redis.max_idle") maxActive := viper.GetInt("redis.max_active") idleTimeout := viper.GetDuration("redis.timeout") pool := &redis.Pool{ MaxIdle: maxIdle, MaxActive: maxActive, IdleTimeout: idleTimeout, Dial: func() (redis.Conn, error) { addr, err := s.MasterAddr() if err != nil { return nil, err } if conn, err := redis.Dial("tcp", addr, opts...); nil != err { return nil, err } else { return conn, nil } }, TestOnBorrow: func(c redis.Conn, t time.Time) error { if !sentinel.TestRole(c, "master") { return fmt.Errorf("redis sentinel role check failed") } else { return nil } }, } return &SentinelAdapter{ pool: pool, }, nil } // 关闭Redis连接 func (a *SentinelAdapter) Close() error { return a.pool.Close() } // 执行Redis命令 func (a *SentinelAdapter) Do(commandName string, args ...interface{}) (interface{}, error) { conn := a.pool.Get() defer func(conn redis.Conn) { _ = conn.Close() }(conn) if nil == conn { return nil, ErrRedisConnNil } else { return conn.Do(commandName, args...) } } // 返回命令管道操作对象 func (a *SentinelAdapter) Pipeline() IRedisPipeline { return &RedigoPipeline{ // sentinel库兼容redigo库,返回RedigoPipeline即可 conn: a.pool.Get(), } }