github.com/whoyao/protocol@v0.0.0-20230519045905-2d8ace718ca5/redis/redis.go (about)

     1  package redis
     2  
     3  import (
     4  	"context"
     5  	"crypto/tls"
     6  
     7  	"github.com/pkg/errors"
     8  	"github.com/redis/go-redis/v9"
     9  
    10  	"github.com/whoyao/protocol/logger"
    11  )
    12  
    13  var ErrNotConfigured = errors.New("Redis is not configured")
    14  
    15  type RedisConfig struct {
    16  	Address           string   `yaml:"address"`
    17  	Username          string   `yaml:"username"`
    18  	Password          string   `yaml:"password"`
    19  	DB                int      `yaml:"db"`
    20  	UseTLS            bool     `yaml:"use_tls"`
    21  	MasterName        string   `yaml:"sentinel_master_name"`
    22  	SentinelUsername  string   `yaml:"sentinel_username"`
    23  	SentinelPassword  string   `yaml:"sentinel_password"`
    24  	SentinelAddresses []string `yaml:"sentinel_addresses"`
    25  	ClusterAddresses  []string `yaml:"cluster_addresses"`
    26  	// for clustererd mode only, number of redirects to follow, defaults to 2
    27  	MaxRedirects *int `yaml:"max_redirects"`
    28  }
    29  
    30  func (r *RedisConfig) IsConfigured() bool {
    31  	if r.Address != "" {
    32  		return true
    33  	}
    34  	if len(r.SentinelAddresses) > 0 {
    35  		return true
    36  	}
    37  	if len(r.ClusterAddresses) > 0 {
    38  		return true
    39  	}
    40  	return false
    41  }
    42  
    43  func (r *RedisConfig) GetMaxRedirects() int {
    44  	if r.MaxRedirects != nil {
    45  		return *r.MaxRedirects
    46  	}
    47  	return 2
    48  }
    49  
    50  func GetRedisClient(conf *RedisConfig) (redis.UniversalClient, error) {
    51  	if conf == nil {
    52  		return nil, nil
    53  	}
    54  
    55  	if !conf.IsConfigured() {
    56  		return nil, ErrNotConfigured
    57  	}
    58  
    59  	var rcOptions *redis.UniversalOptions
    60  	var rc redis.UniversalClient
    61  	var tlsConfig *tls.Config
    62  
    63  	if conf.UseTLS {
    64  		tlsConfig = &tls.Config{
    65  			MinVersion: tls.VersionTLS12,
    66  		}
    67  	}
    68  
    69  	if len(conf.SentinelAddresses) > 0 {
    70  		logger.Infow("connecting to redis", "sentinel", true, "addr", conf.SentinelAddresses, "masterName", conf.MasterName)
    71  		rcOptions = &redis.UniversalOptions{
    72  			Addrs:            conf.SentinelAddresses,
    73  			SentinelUsername: conf.SentinelUsername,
    74  			SentinelPassword: conf.SentinelPassword,
    75  			MasterName:       conf.MasterName,
    76  			Username:         conf.Username,
    77  			Password:         conf.Password,
    78  			DB:               conf.DB,
    79  			TLSConfig:        tlsConfig,
    80  		}
    81  	} else if len(conf.ClusterAddresses) > 0 {
    82  		logger.Infow("connecting to redis", "cluster", true, "addr", conf.ClusterAddresses)
    83  		rcOptions = &redis.UniversalOptions{
    84  			Addrs:        conf.ClusterAddresses,
    85  			Username:     conf.Username,
    86  			Password:     conf.Password,
    87  			DB:           conf.DB,
    88  			TLSConfig:    tlsConfig,
    89  			MaxRedirects: conf.GetMaxRedirects(),
    90  		}
    91  	} else {
    92  		logger.Infow("connecting to redis", "simple", true, "addr", conf.Address)
    93  		rcOptions = &redis.UniversalOptions{
    94  			Addrs:     []string{conf.Address},
    95  			Username:  conf.Username,
    96  			Password:  conf.Password,
    97  			DB:        conf.DB,
    98  			TLSConfig: tlsConfig,
    99  		}
   100  	}
   101  	rc = redis.NewUniversalClient(rcOptions)
   102  
   103  	if err := rc.Ping(context.Background()).Err(); err != nil {
   104  		err = errors.Wrap(err, "unable to connect to redis")
   105  		return nil, err
   106  	}
   107  
   108  	return rc, nil
   109  }