# 6.2 Redis

# 6.2.1 第三方库

# 6.2.2 配置参数

名称 类型 描述
addrs string 连接地址
db int 数据库号,默认为0
username string 用户名,默认空
password string 密码,默认空
keyFile string 私钥文件,默认空
certFile string 证书文件,默认空
caFile string CA证书文件,默认空
maxRetries int 网络相关的错误最大重试次数,默认3次
poolSize int 最大连接池限制,默认为200个连接
minIdleConns int 最小空闲连接数,默认10个连接
dialTimeout string 拨号超时时间,支持单位:纳秒(ns)、微秒(us 或 µs)、毫秒(ms)、秒(s)、分(m)、小时(h)、天(d)。默认为5s
idleTimeout string 连接最大空闲时间,支持单位:纳秒(ns)、微秒(us 或 µs)、毫秒(ms)、秒(s)、分(m)、小时(h)、天(d)。默认0s
readTimeout string 读超时,支持单位:纳秒(ns)、微秒(us 或 µs)、毫秒(ms)、秒(s)、分(m)、小时(h)、天(d)。默认1s
writeTimeout string 写超时,支持单位:纳秒(ns)、微秒(us 或 µs)、毫秒(ms)、秒(s)、分(m)、小时(h)、天(d)。默认1s

# 6.2.3 示例代码

以下完整示例详见:third-redis-example (opens new window)

  1. 组件封装

文件位置:third-redis-example/redis/redis.go (opens new window)

package redis

import (
	"fmt"
	"time"

	"github.com/dobyte/due/v2/core/pool"
	"github.com/dobyte/due/v2/core/tls"
	"github.com/dobyte/due/v2/etc"
	"github.com/dobyte/due/v2/log"
	"github.com/go-redis/redis/v8"
)

var factory = pool.NewFactory(func(name string) (Redis, error) {
	return NewInstance(fmt.Sprintf("etc.redis.%s", name))
})

type (
	Redis  = redis.UniversalClient
	Script = redis.Script
)

type Config struct {
	Addrs        []string      `json:"addrs"`
	DB           int           `json:"db"`
	Username     string        `json:"username"`
	Password     string        `json:"password"`
	CertFile     string        `json:"certFile"`
	KeyFile      string        `json:"keyFile"`
	CaFile       string        `json:"caFile"`
	MaxRetries   int           `json:"maxRetries"`
	PoolSize     int           `json:"poolSize"`
	MinIdleConns int           `json:"minIdleConns"`
	IdleTimeout  time.Duration `json:"idleTimeout"`
	DialTimeout  time.Duration `json:"dialTimeout"`
	ReadTimeout  time.Duration `json:"readTimeout"`
	WriteTimeout time.Duration `json:"writeTimeout"`
}

// Instance 获取实例
func Instance(name ...string) Redis {
	var (
		err error
		ins Redis
	)

	if len(name) == 0 {
		ins, err = factory.Get("default")
	} else {
		ins, err = factory.Get(name[0])
	}

	if err != nil {
		log.Fatalf("create redis instance failed: %v", err)
	}

	return ins
}

// NewInstance 新建实例
func NewInstance[T string | Config | *Config](config T) (Redis, error) {
	var (
		conf *Config
		v    any = config
	)

	switch c := v.(type) {
	case string:
		conf = &Config{
			Addrs:        etc.Get(fmt.Sprintf("%s.addrs", c)).Strings(),
			DB:           etc.Get(fmt.Sprintf("%s.db", c)).Int(),
			CertFile:     etc.Get(fmt.Sprintf("%s.certFile", c)).String(),
			KeyFile:      etc.Get(fmt.Sprintf("%s.keyFile", c)).String(),
			CaFile:       etc.Get(fmt.Sprintf("%s.caFile", c)).String(),
			Username:     etc.Get(fmt.Sprintf("%s.username", c)).String(),
			Password:     etc.Get(fmt.Sprintf("%s.password", c)).String(),
			MaxRetries:   etc.Get(fmt.Sprintf("%s.maxRetries", c), 3).Int(),
			PoolSize:     etc.Get(fmt.Sprintf("%s.poolSize", c), 200).Int(),
			MinIdleConns: etc.Get(fmt.Sprintf("%s.minIdleConns", c), 20).Int(),
			DialTimeout:  etc.Get(fmt.Sprintf("%s.dialTimeout", c), "3s").Duration(),
			IdleTimeout:  etc.Get(fmt.Sprintf("%s.idleTimeout", c)).Duration(),
			ReadTimeout:  etc.Get(fmt.Sprintf("%s.readTimeout", c), "1s").Duration(),
			WriteTimeout: etc.Get(fmt.Sprintf("%s.writeTimeout", c), "1s").Duration(),
		}
	case Config:
		conf = &c
	case *Config:
		conf = c
	}

	options := &redis.UniversalOptions{
		Addrs:        conf.Addrs,
		DB:           conf.DB,
		Username:     conf.Username,
		Password:     conf.Password,
		MaxRetries:   conf.MaxRetries,
		PoolSize:     conf.PoolSize,
		MinIdleConns: conf.MinIdleConns,
		IdleTimeout:  conf.IdleTimeout,
		DialTimeout:  conf.DialTimeout,
		ReadTimeout:  conf.ReadTimeout,
		WriteTimeout: conf.WriteTimeout,
	}

	if conf.CertFile != "" && conf.KeyFile != "" && conf.CaFile != "" {
		if tlsConfig, err := tls.MakeRedisTLSConfig(conf.CertFile, conf.KeyFile, conf.CaFile); err != nil {
			return nil, err
		} else {
			options.TLSConfig = tlsConfig
		}
	}

	return redis.NewUniversalClient(options), nil
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
  1. 配置示例

文件位置:third-redis-example/etc/etc.toml (opens new window)

[redis.default]
    # 连接地址
    addrs = ["127.0.0.1:6379"]
    # 数据库号,默认为0
    db = 0
    # 用户名,默认空
    username = ""
    # 密码,默认空
    password = ""
    # 私钥文件
    keyFile = ""
    # 证书文件
    certFile = ""
    # CA证书文件
    caFile = ""
    # 网络相关的错误最大重试次数,默认3次
    maxRetries = 3
    # 最大连接池限制,默认为200个连接
    poolSize = 200
    # 最小空闲连接数,默认10个连接
    minIdleConns = 10
	# 拨号超时时间,支持单位:纳秒(ns)、微秒(us | µs)、毫秒(ms)、秒(s)、分(m)、小时(h)、天(d)。默认5s
    dialTimeout = "5s"
    # 连接最大空闲时间,支持单位:纳秒(ns)、微秒(us | µs)、毫秒(ms)、秒(s)、分(m)、小时(h)、天(d)。默认0s
    idleTimeout = "0s"
	# 读超时,支持单位:纳秒(ns)、微秒(us | µs)、毫秒(ms)、秒(s)、分(m)、小时(h)、天(d)。默认1s
    readTimeout = "1s"
	# 写超时,支持单位:纳秒(ns)、微秒(us | µs)、毫秒(ms)、秒(s)、分(m)、小时(h)、天(d)。默认1s
    writeTimeout = "1s"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
  1. 组件调用

文件位置:third-redis-example/main.go (opens new window)

package main

import (
	"context"
	"third-redis-example/redis"

	"github.com/dobyte/due/v2/log"
)

func main() {
	rds := redis.Instance("default")

	if result, err := rds.Ping(context.Background()).Result(); err != nil {
		log.Errorf("redis connection error: %v", err)
	} else {
		log.Infof("redis ping result: %v", result)
	}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18