1
0
mirror of https://github.com/silenceper/wechat.git synced 2026-02-09 07:02:27 +08:00

feat(redis): 优化配置语义并增强超时与连接池能力,同时保持向后兼容 (#869)

* fix: correct non-standard 'yml' tag to 'yaml' in RedisOpts

* fix: apply MaxActive config to Redis PoolSize

* fix: clarify config semantics, enhance timeout & pool options, and maintain backward compatibility

* test: update unit test for redis

* refactor: apply suggestions from code review

* test: add comprehensive coverage for redis

* refactor: resolve funlen linter errors in redis unit tests

* refactor: remove empty else-if branch in NewRedis function
This commit is contained in:
Gophlet
2026-01-08 09:49:41 +08:00
committed by GitHub
parent 78c00a9124
commit 7d93d1b9c8
2 changed files with 315 additions and 11 deletions

58
cache/redis.go vendored
View File

@@ -17,14 +17,24 @@ type Redis struct {
// RedisOpts redis 连接属性
type RedisOpts struct {
Host string `json:"host" yml:"host"`
Username string `json:"username" yaml:"username"`
Password string `json:"password" yml:"password"`
Database int `json:"database" yml:"database"`
MaxIdle int `json:"max_idle" yml:"max_idle"`
MaxActive int `json:"max_active" yml:"max_active"`
IdleTimeout int `json:"idle_timeout" yml:"idle_timeout"` // second
UseTLS bool `json:"use_tls" yml:"use_tls"` // 是否使用TLS
Host string `json:"host" yaml:"host"`
Username string `json:"username" yaml:"username"`
Password string `json:"password" yaml:"password"`
Database int `json:"database" yaml:"database"`
MinIdleConns int `json:"min_idle_conns" yaml:"min_idle_conns"` // 最小空闲连接数
PoolSize int `json:"pool_size" yaml:"pool_size"` // 连接池大小0 表示使用默认值(即 CPU 核心数 * 10
MaxRetries int `json:"max_retries" yaml:"max_retries"` // 最大重试次数,-1 表示不重试0 表示使用默认值(即 3 次)
DialTimeout int `json:"dial_timeout" yaml:"dial_timeout"` // 连接超时时间0 表示使用默认值(即 5 秒)
ReadTimeout int `json:"read_timeout" yaml:"read_timeout"` // 读取超时时间(秒),-1 表示不超时0 表示使用默认值(即 3 秒)
WriteTimeout int `json:"write_timeout" yaml:"write_timeout"` // 写入超时时间(秒),-1 表示不超时0 表示使用默认值(即 ReadTimeout
PoolTimeout int `json:"pool_timeout" yaml:"pool_timeout"` // 连接池获取连接超时时间0 表示使用默认值(即 ReadTimeout + 1 秒)
IdleTimeout int `json:"idle_timeout" yaml:"idle_timeout"` // 空闲连接超时时间(秒),-1 表示禁用空闲连接超时检查0 表示使用默认值(即 5 分钟)
UseTLS bool `json:"use_tls" yaml:"use_tls"` // 是否使用 TLS
// Deprecated: 应使用 MinIdleConns 代替
MaxIdle int `json:"max_idle" yaml:"max_idle"`
// Deprecated: 应使用 PoolSize 代替
MaxActive int `json:"max_active" yaml:"max_active"`
}
// NewRedis 实例化
@@ -34,10 +44,38 @@ func NewRedis(ctx context.Context, opts *RedisOpts) *Redis {
DB: opts.Database,
Username: opts.Username,
Password: opts.Password,
IdleTimeout: time.Second * time.Duration(opts.IdleTimeout),
MinIdleConns: opts.MaxIdle,
MinIdleConns: opts.MinIdleConns,
PoolSize: opts.PoolSize,
MaxRetries: opts.MaxRetries,
}
// 兼容旧的 MaxIdle 参数,仅在未显式设置 MinIdleConns 时生效
if opts.MaxIdle > 0 && opts.MinIdleConns == 0 {
uniOpt.MinIdleConns = opts.MaxIdle
}
// 兼容旧的 MaxActive 参数,仅在未显式设置 PoolSize 时生效
if opts.MaxActive > 0 && opts.PoolSize == 0 {
uniOpt.PoolSize = opts.MaxActive
}
applyTimeout := func(seconds int, target *time.Duration) {
if seconds > 0 {
*target = time.Duration(seconds) * time.Second
} else if seconds == -1 {
// 当 seconds 为 -1 时,表示禁用超时:按 go-redis 约定,将超时时间设置为负值(如 -1ns代表「无超时」
*target = -1
}
// 当 seconds 为 0 时,使用 go-redis 的默认超时配置:
// 不修改 target保持其零值0由 go-redis 解释为“使用默认值”
}
applyTimeout(opts.DialTimeout, &uniOpt.DialTimeout)
applyTimeout(opts.ReadTimeout, &uniOpt.ReadTimeout)
applyTimeout(opts.WriteTimeout, &uniOpt.WriteTimeout)
applyTimeout(opts.PoolTimeout, &uniOpt.PoolTimeout)
applyTimeout(opts.IdleTimeout, &uniOpt.IdleTimeout)
if opts.UseTLS {
h, _, err := net.SplitHostPort(opts.Host)
if err != nil {