Compare commits

..

22 Commits

Author SHA1 Message Date
ef3a36f288 cmd统一使用小写 2025-04-21 17:06:55 +08:00
5d1ebcf505 redis client支持设置mock模式 2025-04-21 16:42:28 +08:00
ac633385b7 update go mod 2025-04-20 18:12:50 +08:00
258311256f 升级 cmd 枚举值类型 2024-11-25 17:35:50 +08:00
a85ebc0203 增加获取key的有效期 2024-10-09 18:18:49 +08:00
ec5f5f0161 Merge pull request 'redis client自适应读写命令选择主库 OR 读库' (#4) from feature/upgrade into master
Reviewed-on: #4
2024-10-08 16:44:37 +08:00
2e05d47fb7 增加常用写命令枚举 2024-10-08 16:43:58 +08:00
6f502a5bdd redis client自适应读写命令选择主库 OR 读库 2024-10-08 16:31:59 +08:00
eec9374d48 update go mod 2024-10-08 15:56:38 +08:00
c315db9a8a 支持设置日志扩展字段 2024-06-21 18:48:06 +08:00
9daae92046 修复构建redis结果读取的异常 + 增加exist方法 2024-06-21 12:43:26 +08:00
27e193a0ea 支持配置选择使用的数据库 2024-06-20 18:44:55 +08:00
e8b63fb863 cluster -> single 2024-06-20 18:38:23 +08:00
f11c0a8216 save code 2024-06-20 18:22:17 +08:00
63e4412d67 update code 2024-06-20 18:09:25 +08:00
cbab3ebbc2 update client 2024-06-20 14:58:06 +08:00
3de0fe084f Merge pull request 'feature/support_v8_v9' (#3) from feature/support_v8_v9 into master
Reviewed-on: #3
2024-06-20 11:20:08 +08:00
0838c037cd 切换go-redis库 2024-06-20 11:18:46 +08:00
4a8a262d0f save code 2024-06-19 22:08:12 +08:00
20b30f92a7 切换v8库, 适配流控 2024-06-19 21:57:26 +08:00
cec7fa76e5 升级增加client 2024-06-19 21:21:34 +08:00
7e866b3f1f fix 2024-06-19 20:59:20 +08:00
12 changed files with 335 additions and 771 deletions

View File

@ -9,8 +9,9 @@ package abstract
import (
"context"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/redis/define"
"github.com/redis/go-redis/v9"
"github.com/go-redis/redismock/v9"
"go.uber.org/zap"
)
@ -20,11 +21,13 @@ import (
//
// Date : 15:09 2024/6/18
type IRedisClient interface {
GetRealClient(instanceFlag string) *redis.ClusterClient // 获取客户端连接
GetRealClientWithError(instanceFlag string) (*redis.ClusterClient, error) // 获取带error的客户端连接
AddClient(instanceFlag string, instanceConfig *redis.ClusterOptions) error // 添加新的客户端连接
RemoveClient(instanceFlag string) // 移除一个客户端连接
SetLogger(loggerInstance *zap.Logger) // 设置日志实例, 全局生效, 而非针对某一个实例
Exec(ctx context.Context, instanceFlag string, command string, args ...any) *define.RedisResult // 执行任意命令
SetCommandWhiteList(command []string) // 设置命令的白名单,全局生效, 而非单独针对某一个实例
GetRealClient(instanceFlag string) *define.ClientInfo // 获取客户端连接
GetRealClientWithError(instanceFlag string) (*define.ClientInfo, error) // 获取带error的客户端连接
AddClient(instanceFlag string, instanceConfig *define.Config) error // 添加新的客户端连接
RemoveClient(instanceFlag string) // 移除一个客户端连接
SetLogger(loggerInstance *zap.Logger, extraLogFieldList []string) // 设置日志实例, 全局生效, 而非针对某一个实例
Exec(ctx context.Context, instanceFlag string, command consts.RedisCmd, args ...any) *define.RedisResult // 执行任意命令
SetCommandWhiteList(command []consts.RedisCmd) // 设置命令的白名单,全局生效, 而非单独针对某一个实例
SetMockMode() // 设置mock模式, 这是单元测试专用的, 生产环境不要使用!!!!!!
GetMockInstance() redismock.ClientMock // 数据mock实例
}

View File

@ -1,37 +0,0 @@
// Package apply ...
//
// Description : apply ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2023-02-13 11:24
package apply
import (
"git.zhangdeman.cn/zhangdeman/redis"
)
var (
// Cache 数据缓存的场景
Cache *cache
)
type cache struct {
}
// Set 设置缓存
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:28 2023/2/13
func (c *cache) Set(ctx *redis.Context, key string, value interface{}) error {
var (
err error
rc *redis.RealClient
)
if rc, err = redis.Client.GetRedisClientWithError(ctx.Flag); nil != err {
return err
}
return rc.Master.Set(nil, key, value, -1).Err()
}

188
client.go
View File

@ -9,32 +9,41 @@ package redis
import (
"context"
"git.zhangdeman.cn/zhangdeman/redis/abstract"
"git.zhangdeman.cn/zhangdeman/redis/define"
"git.zhangdeman.cn/zhangdeman/wrapper"
"github.com/pkg/errors"
redisClient "github.com/redis/go-redis/v9"
"go.uber.org/zap"
"git.zhangdeman.cn/zhangdeman/consts"
"github.com/go-redis/redismock/v9"
"strings"
"sync"
"time"
"git.zhangdeman.cn/zhangdeman/redis/abstract"
"git.zhangdeman.cn/zhangdeman/redis/define"
wrapperOperate "git.zhangdeman.cn/zhangdeman/wrapper"
"github.com/pkg/errors"
redisClient "github.com/redis/go-redis/v9"
"go.uber.org/zap"
)
var Client abstract.IRedisClient
var (
Client abstract.IRedisClient
)
func init() {
Client = &OwnClient{
lock: &sync.RWMutex{},
instanceTable: make(map[string]*redisClient.ClusterClient),
instanceTable: make(map[string]*define.ClientInfo),
whiteCommandTable: make(map[string]bool),
}
}
type OwnClient struct {
lock *sync.RWMutex
instanceTable map[string]*redisClient.ClusterClient
instanceTable map[string]*define.ClientInfo
whiteCommandTable map[string]bool
logger *zap.Logger
extraLogFieldList []string
mockMode bool
mockInstance redismock.ClientMock
mockClient *redisClient.Client
}
func (o *OwnClient) isAllowCommand(command string) bool {
@ -57,27 +66,31 @@ func (o *OwnClient) isAllowCommand(command string) bool {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:05 2024/6/19
func (o *OwnClient) Exec(ctx context.Context, instanceFlag string, command string, args ...any) *define.RedisResult {
func (o *OwnClient) Exec(ctx context.Context, instanceFlag string, command consts.RedisCmd, args ...any) *define.RedisResult {
if nil == ctx {
ctx = context.Background()
}
var (
instance *redisClient.ClusterClient
instance *define.ClientInfo
)
cmdParamList := []any{
command,
strings.ToLower(command.String()), // redis 命令不区分大小写, 统一使用小写
}
argStrList := make([]string, 0)
for _, itemArg := range args {
argStrList = append(argStrList, wrapper.AnyDataType(itemArg).ToString().Value())
argStrList = append(argStrList, wrapperOperate.AnyDataType(itemArg).ToString().Value())
cmdParamList = append(cmdParamList, itemArg)
}
res := &define.RedisResult{
StartTime: time.Now().UnixMilli(),
FinishTime: 0,
UsedTime: 0,
Result: "",
Command: command,
ArgList: argStrList,
Err: nil,
StartTime: time.Now().UnixMilli(),
FinishTime: 0,
UsedTime: 0,
Result: "",
Command: command,
ArgList: argStrList,
Err: nil,
InstanceFlag: instanceFlag,
}
defer func() {
res.FinishTime = time.Now().UnixMilli()
@ -86,15 +99,21 @@ func (o *OwnClient) Exec(ctx context.Context, instanceFlag string, command strin
// 未注入日志实例
return
}
o.logger.Info(
"Redis命令执行记录",
logDataList := []zap.Field{
zap.Int64("start_time", res.StartTime),
zap.Int64("finish_time", res.FinishTime),
zap.Int64("used_time", res.UsedTime),
zap.String("command", res.Command),
zap.String("command", res.Command.String()),
zap.String("arg_list", strings.Join(res.ArgList, " ")),
zap.String("execute_result", res.Result),
zap.Error(res.Err),
}
for _, item := range o.extraLogFieldList {
logDataList = append(logDataList, zap.Any(item, ctx.Value(item)))
}
o.logger.Info(
"Redis命令执行记录",
logDataList...,
)
}()
if instance, res.Err = o.GetRealClientWithError(instanceFlag); nil != res.Err {
@ -103,11 +122,25 @@ func (o *OwnClient) Exec(ctx context.Context, instanceFlag string, command strin
if nil == ctx {
ctx = context.Background()
}
cmdRes := instance.Do(ctx, cmdParamList...)
if instance.ReadOnly && o.isWriteCommand(command) {
// 只读实例, 尝试执行写命令
res.Err = errors.New(instanceFlag + " : instance is read only")
return res
}
if instance.ReadOnly && o.isWriteCommand(command) && instance.MasterClient() == nil {
// 写命令, 没有主库连接
res.Err = errors.New(instanceFlag + " : instance master client is nil")
return res
}
redisRealClient := instance.MasterClient()
if !o.isWriteCommand(command) {
redisRealClient = instance.SlaveClient()
}
cmdRes := redisRealClient.Do(ctx, cmdParamList...)
if res.Err = cmdRes.Err(); nil != res.Err {
return res
}
res.Result = cmdRes.String()
res.Result = wrapperOperate.AnyDataType(cmdRes.Val()).ToString().Value()
return res
}
@ -116,21 +149,21 @@ func (o *OwnClient) Exec(ctx context.Context, instanceFlag string, command strin
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:02 2024/6/19
func (o *OwnClient) SetCommandWhiteList(commandList []string) {
func (o *OwnClient) SetCommandWhiteList(commandList []consts.RedisCmd) {
o.lock.Lock()
defer o.lock.Unlock()
for _, itemCommand := range commandList {
o.whiteCommandTable[strings.ToLower(strings.TrimSpace(itemCommand))] = true
o.whiteCommandTable[strings.ToLower(strings.TrimSpace(itemCommand.String()))] = true
}
}
func (o *OwnClient) GetRealClient(instanceFlag string) *redisClient.ClusterClient {
func (o *OwnClient) GetRealClient(instanceFlag string) *define.ClientInfo {
o.lock.RLock()
defer o.lock.RUnlock()
return o.instanceTable[instanceFlag]
}
func (o *OwnClient) GetRealClientWithError(instanceFlag string) (*redisClient.ClusterClient, error) {
func (o *OwnClient) GetRealClientWithError(instanceFlag string) (*define.ClientInfo, error) {
o.lock.RLock()
defer o.lock.RUnlock()
instance, exist := o.instanceTable[instanceFlag]
@ -140,11 +173,27 @@ func (o *OwnClient) GetRealClientWithError(instanceFlag string) (*redisClient.Cl
return instance, nil
}
func (o *OwnClient) AddClient(instanceFlag string, instanceConfig *redisClient.ClusterOptions) error {
instance := redisClient.NewClusterClient(instanceConfig)
func (o *OwnClient) AddClient(instanceFlag string, instanceConfig *define.Config) error {
if nil == instanceConfig.Master && !instanceConfig.ReadOnly {
// 不是只读, 则要求 主库配置 和 从库配置都要存在
return errors.New(instanceFlag + " : master config is nil")
}
clientInfo := &define.ClientInfo{
ReadOnly: instanceConfig.ReadOnly,
Master: nil,
Slave: nil,
}
if nil != instanceConfig.Master {
clientInfo.Master = o.newClient(instanceConfig.Master)
}
if nil != instanceConfig.Slave {
clientInfo.Master = o.newClient(instanceConfig.Slave)
}
o.lock.Lock()
defer o.lock.Unlock()
o.instanceTable[instanceFlag] = instance
o.instanceTable[instanceFlag] = clientInfo
return nil
}
@ -154,6 +203,79 @@ func (o *OwnClient) RemoveClient(instanceFlag string) {
delete(o.instanceTable, instanceFlag)
}
func (o *OwnClient) SetLogger(loggerInstance *zap.Logger) {
func (o *OwnClient) SetLogger(loggerInstance *zap.Logger, extraLogFieldList []string) {
o.logger = loggerInstance
o.extraLogFieldList = extraLogFieldList
}
// isWriteCommand 判断是否写命令
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:22 2024/10/8
func (o *OwnClient) isWriteCommand(command consts.RedisCmd) bool {
return wrapperOperate.ArrayType([]consts.RedisCmd{
consts.RedisCommandDel,
consts.RedisCommandSet,
consts.RedisCommandLpush,
consts.RedisCommandRpush,
consts.RedisCommandMSet,
consts.RedisCommandPublish,
consts.RedisCommandPsubScribe,
}).Has(consts.RedisCmd(strings.ToUpper(command.String()))) >= 0
}
// SetMockMode 启用mock, 非单元测试不要使用!!!!!!!!
func (o *OwnClient) SetMockMode() {
o.mockMode = true
o.mockClient, o.mockInstance = redismock.NewClientMock()
}
// GetMockInstance 获取mock实例
func (o *OwnClient) GetMockInstance() redismock.ClientMock {
return o.mockInstance
}
// newClient 获取客户端连接
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:12 2024/10/8
func (o *OwnClient) newClient(instanceConfig *define.Options) *redisClient.Client {
if o.mockMode {
// mock模式下, 直接返回mock实例
return o.mockClient
}
return redisClient.NewClient(&redisClient.Options{
DB: instanceConfig.DB,
Addr: instanceConfig.Addr,
ClientName: instanceConfig.ClientName,
Dialer: nil,
OnConnect: func(ctx context.Context, cn *redisClient.Conn) error {
return nil
},
// Protocol: 0,
Username: instanceConfig.Username,
Password: instanceConfig.Password,
// CredentialsProvider: nil,
// CredentialsProviderContext: nil,
MaxRetries: instanceConfig.MaxRetries,
MinRetryBackoff: time.Duration(instanceConfig.MinRetryBackoff) * time.Millisecond,
MaxRetryBackoff: time.Duration(instanceConfig.MaxRetryBackoff) * time.Millisecond,
DialTimeout: time.Duration(instanceConfig.DialTimeout) * time.Millisecond,
ReadTimeout: time.Duration(instanceConfig.ReadTimeout) * time.Millisecond,
WriteTimeout: time.Duration(instanceConfig.WriteTimeout) * time.Millisecond,
// ContextTimeoutEnabled: instanceConfig.ContextTimeoutEnabled,
PoolFIFO: instanceConfig.PoolFIFO,
PoolSize: instanceConfig.PoolSize,
PoolTimeout: time.Duration(instanceConfig.PoolTimeout) * time.Millisecond,
MinIdleConns: instanceConfig.MinIdleConn,
// MaxIdleConns: instanceConfig.MaxIdleConn,
// MaxActiveConns: instanceConfig.MaxActiveConn,
// ConnMaxIdleTime: time.Duration(instanceConfig.ConnMaxIdleTime) * time.Second,
// ConnMaxLifetime: time.Duration(instanceConfig.ConnMaxIdleTime) * time.Second,
TLSConfig: nil,
// DisableIndentity: instanceConfig.DisableIdentity,
// IdentitySuffix: instanceConfig.IdentitySuffix,
})
}

149
config.go
View File

@ -1,149 +0,0 @@
// Package redis ...
//
// Description : redis ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2022-06-15 11:52
package redis
import (
"fmt"
"time"
"github.com/go-redis/redis/v8"
"git.zhangdeman.cn/zhangdeman/logger"
)
// FullConfig 完整配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:23 2022/6/15
type FullConfig struct {
ExtraFieldList []string `json:"extra_field_list" yaml:"extra_field_list"` // 从上下文抽取的字段信息
Logger *logger.InputLogConfig `json:"logger" yaml:"logger"` // 日志配置
Master *Config `json:"master" yaml:"master"` // 主节点
Slave *Config `json:"slave" yaml:"slave"` // 从节点
}
// Config redis的配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:52 2022/6/15
type Config struct {
Network string `json:"network" yaml:"network"` // 连接方式 tcp 或 unix , 默认 tcp
Host string `yaml:"host" json:"host"` // 地址
Port int `yaml:"port" json:"port"` // 端口
// Dialer creates new network connection and has priority over
// Network and Addr options.
// Dialer func(ctx context.Context, network, addr string) (net.Conn, error)
// Hook that is called when new connection is established.
// OnConnect func(ctx context.Context, cn *redis.Conn) error
// Use the specified Username to authenticate the current connection
// with one of the connections defined in the ACL list when connecting
// to a Redis 6.0 instance, or greater, that is using the Redis ACL system.
Username string `json:"username" yaml:"username"` // 账号
// Optional password. Must match the password specified in the
// requirepass server configuration option (if connecting to a Redis 5.0 instance, or lower),
// or the User Password when connecting to a Redis 6.0 instance, or greater,
// that is using the Redis ACL system.
Password string `json:"password" yaml:"password"` // 密码
// Database to be selected after connecting to the server.
DB int `json:"db" yaml:"db"` // 选中的数据库
// Maximum number of retries before giving up.
// Default is 3 retries; -1 (not 0) disables retries.
MaxRetries int `json:"max_retries" yaml:"max_retries"` // 最大重试次数, 默认 3 , -1 为不重试
// Minimum backoff between each retry.
// Default is 8 milliseconds; -1 disables backoff.
MinRetryBackoff int64 `json:"min_retry_backoff" yaml:"min_retry_backoff"` // 最小重试的时间间隔, 默认 8ms, -1禁用
// Maximum backoff between each retry.
// Default is 512 milliseconds; -1 disables backoff.
MaxRetryBackoff int `json:"max_retry_backoff" yaml:"max_retry_backoff"` // 最大重试的时间间隔, 默认 512ms, -1禁用
// Dial timeout for establishing new connections.
// Default is 5 seconds.
DialTimeout int64 `json:"dial_timeout" yaml:"dial_timeout"` // 建立新连接的超时时间, 默认 5s
// Timeout for socket reads. If reached, commands will fail
// with a timeout instead of blocking. Use value -1 for no timeout and 0 for default.
// Default is 3 seconds.
ReadTimeout int64 `json:"read_timeout" yaml:"read_timeout"` // 读取超时时间,默认 3s , -1 不设置超时
// Timeout for socket writes. If reached, commands will fail
// with a timeout instead of blocking.
// Default is ReadTimeout.
WriteTimeout int64 `json:"write_timeout" yaml:"write_timeout"` // 写入超时时间, 默认值和 ReadTimeout 配置一致
// Type of connection pool.
// true for FIFO pool, false for LIFO pool.
// Note that fifo has higher overhead compared to lifo.
PoolFIFO bool `json:"pool_fifo" yaml:"pool_fifo"` // 连接吃采用 FIFO
// Maximum number of socket connections.
// Default is 10 connections per every available CPU as reported by runtime.GOMAXPROCS.
PoolSize int `json:"pool_size" yaml:"pool_size"` // 连接池大小, 默认 runtime.GOMAXPROCS * 10
// Minimum number of idle connections which is useful when establishing
// new connection is slow.
MinIdleConns int `json:"min_idle_conns" yaml:"min_idle_conns"` // 最小的 空闲 连接数数量
// Connection age at which client retires (closes) the connection.
// Default is to not close aged connections.
MaxConnAge int64 `json:"max_conn_age" yaml:"max_conn_age"` // 连接最大的存活时常
// Amount of time client waits for connection if all connections
// are busy before returning an error.
// Default is ReadTimeout + 1 second.
PoolTimeout int64 `json:"pool_timeout" yaml:"pool_timeout"` // 连接池无可用连接, 等待的时常, 默认值 ReadTimeout + 1
// Amount of time after which client closes idle connections.
// Should be less than server's timeout.
// Default is 5 minutes. -1 disables idle timeout check.
IdleTimeout int64 `json:"idle_timeout" yaml:"idle_timeout"` // 空闲链接的超时时间, 默认 5 分钟 -1 金童
// Frequency of idle checks made by idle connections reaper.
// Default is 1 minute. -1 disables idle connections reaper,
// but idle connections are still discarded by the client
// if IdleTimeout is set.
IdleCheckFrequency int64 `json:"idle_check_frequency" yaml:"idle_check_frequency"` // 空闲连接检查频率, 默认 1 分钟, -1 禁用, 注意 : 即使禁用,超过 IdleTimeout 时常的连接也不可被读取到
}
// Config2Options 将 自定义的配置文件转为 redis 包需要的配置格式
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 17:37 2022/6/15
func Config2Options(cfg *Config) *redis.Options {
option := &redis.Options{
Network: cfg.Network,
Addr: fmt.Sprintf("%v:%v", cfg.Host, cfg.Port),
Username: cfg.Username,
Password: cfg.Password,
DB: cfg.DB,
MaxRetries: cfg.MaxRetries,
MinRetryBackoff: time.Duration(cfg.MinRetryBackoff) * time.Millisecond,
MaxRetryBackoff: time.Duration(cfg.MaxRetryBackoff) * time.Millisecond,
DialTimeout: time.Duration(cfg.DialTimeout) * time.Millisecond,
ReadTimeout: time.Duration(cfg.ReadTimeout) * time.Millisecond,
WriteTimeout: time.Duration(cfg.WriteTimeout) * time.Millisecond,
PoolFIFO: cfg.PoolFIFO,
PoolSize: cfg.PoolSize,
MinIdleConns: cfg.MinIdleConns,
MaxConnAge: time.Duration(cfg.MaxConnAge) * time.Millisecond,
PoolTimeout: time.Duration(cfg.PoolTimeout) * time.Millisecond,
IdleTimeout: time.Duration(cfg.IdleTimeout) * time.Millisecond,
IdleCheckFrequency: time.Duration(cfg.IdleCheckFrequency) * time.Millisecond,
TLSConfig: nil,
Limiter: nil,
}
if len(option.Network) == 0 {
option.Network = NetworkTypeTCP
}
return option
}
const (
// NetworkTypeTCP ...
NetworkTypeTCP = "tcp"
// NetworkTypeUnix ...
NetworkTypeUnix = "unix"
)

View File

@ -1,141 +0,0 @@
// Package redis...
//
// Description : redis...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-02-27 8:22 下午
package redis
import (
"context"
"git.zhangdeman.cn/zhangdeman/easymap"
"github.com/gin-gonic/gin"
)
const (
// 默认的 request_id 字段名
defaultRequestIDField = "request_id"
// 默认的message
defaultMessage = "执行redis命令日志记录"
// 耗时字段
defaultUsedTimeField = "used_field"
// 默认的命令字段
defaultCommandField = "command"
// 默认记录 redis标识的字段
defaultFlagField = "flag"
)
// Context 请求上下文
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:25 下午 2021/2/27
type Context struct {
Flag string // 哪个模块的上下文
Ctx context.Context // ctx
GinCtx *gin.Context // http 请求绑定的gin.context
RequestIDField string // requestID 字段名
RequestID string // requestID 此字段有值, 直接使用此值,无值, 去GinCtx 中读取 RequestIDField
Extra easymap.EasyMap // 扩展信息
}
// NewContext 生成一个上下文
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:26 下午 2021/2/27
func NewContext(flag string, of ...SetContextFunc) *Context {
ctx := &Context{
Flag: flag,
Ctx: nil,
GinCtx: nil,
RequestIDField: "",
RequestID: "",
Extra: nil,
}
for _, f := range of {
f(ctx)
}
if nil == ctx.Ctx {
ctx.Ctx = context.Background()
}
if len(ctx.RequestIDField) == 0 {
ctx.RequestIDField = defaultRequestIDField
}
if nil == ctx.Extra {
ctx.Extra = easymap.NewNormal()
}
// requestID 填充
if len(ctx.RequestID) == 0 {
// 先从 gin 读
if nil != ctx.GinCtx {
ctx.RequestID = ctx.GinCtx.GetString(ctx.RequestIDField)
}
// 再从extra读取
if len(ctx.RequestID) == 0 {
ctx.RequestID, _ = ctx.Extra.GetString(ctx.RequestID)
}
}
return ctx
}
// SetContextFunc 设置context参数
type SetContextFunc func(rc *Context)
// WithCtx 设置context
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:30 下午 2021/2/27
func WithCtx(ctx context.Context) SetContextFunc {
return func(rc *Context) {
rc.Ctx = ctx
}
}
// WithGinCtx 设置gin上下文
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:34 下午 2021/2/27
func WithGinCtx(ginCtx *gin.Context) SetContextFunc {
return func(rc *Context) {
rc.GinCtx = ginCtx
}
}
// WithExtra 设置扩展信息
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:36 下午 2021/2/27
func WithExtra(extra easymap.EasyMap) SetContextFunc {
return func(rc *Context) {
rc.Extra = extra
}
}
// WithRequestIDField 设置request_id参数名
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:41 下午 2021/2/27
func WithRequestIDField(requestIDField string) SetContextFunc {
return func(rc *Context) {
rc.RequestIDField = requestIDField
}
}
// WithRequestID ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:42 下午 2021/2/27
func WithRequestID(requestID string) SetContextFunc {
return func(rc *Context) {
rc.RequestID = requestID
}
}

View File

@ -7,23 +7,15 @@
// Date : 2024-06-18 16:12
package define
type ClusterOptions struct {
import redisClient "github.com/redis/go-redis/v9"
type Options struct {
DB int `json:"db" yaml:"db" ini:"db" toml:"db"` // 选择的数据库序号
Network string `json:"network" yaml:"network" ini:"network" toml:"network"` // 网络连接方式
// A seed list of host:port addresses of cluster nodes.
Addrs []string `json:"addrs" yaml:"addrs" ini:"addrs" toml:"addrs"` // 集群IP列表
Addr string `json:"addr" yaml:"addr" ini:"addr" toml:"addr"` // 集群IP列表
// ClientName will execute the `CLIENT SETNAME ClientName` command for each conn.
ClientName string `json:"client_name" yaml:"client_name" ini:"client_name" toml:"client_name"` // 集群名称
// The maximum number of retries before giving up. Command is retried
// on network errors and MOVED/ASK redirects.
// Default is 3 retries.
MaxRedirects int `json:"max_redirects" yaml:"max_redirects" ini:"max_redirects" toml:"max_redirects"` // 最大重试次数
// Enables read-only commands on slave nodes.
ReadOnly bool `json:"read_only" yaml:"read_only" ini:"read_only" toml:"read_only"` // 只读
// Allows routing read-only commands to the closest master or slave node.
// It automatically enables ReadOnly.
RouteByLatency bool `json:"route_by_latency" yaml:"route_by_latency" ini:"route_by_latency" toml:"route_by_latency"`
// Allows routing read-only commands to the random master or slave node.
// It automatically enables ReadOnly.
RouteRandomly bool `json:"route_randomly" yaml:"route_randomly" ini:"route_randomly" toml:"route_randomly"`
Protocol int
Username string `json:"username" yaml:"username" ini:"username" toml:"username"`
@ -51,3 +43,36 @@ type ClusterOptions struct {
IdentitySuffix string `json:"identity_suffix" yaml:"identity_suffix" ini:"identity_suffix" toml:"identity_suffix"` // Add suffix to client name. Default is empty.
}
// Config 数据库连接配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:59 2024/10/8
type Config struct {
ReadOnly bool `json:"readonly" yaml:"readonly" ini:"readonly" toml:"readonly"`
Master *Options `json:"master" yaml:"master" ini:"master" toml:"master"` // 主库配置
Slave *Options `json:"slave" yaml:"slave" ini:"slave" toml:"slave"` // 主库配置
}
// ClientInfo 客户端连接信息
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:06 2024/10/8
type ClientInfo struct {
ReadOnly bool // 是否只读
Master *redisClient.Client // 主库连接
Slave *redisClient.Client // 从库连接
}
func (cf *ClientInfo) MasterClient() *redisClient.Client {
return cf.Master
}
func (cf *ClientInfo) SlaveClient() *redisClient.Client {
if nil != cf.Slave {
return cf.Slave
}
return cf.Master
}

View File

@ -7,18 +7,20 @@
// Date : 2024-06-19 10:49
package define
import "git.zhangdeman.cn/zhangdeman/consts"
// RedisResult redis名玲玲执行结果
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:50 2024/6/19
type RedisResult struct {
InstanceFlag string `json:"instance_flag"` // 实例标识
StartTime int64 `json:"start_time"` // 开始执行时间, 单位 : ms
FinishTime int64 `json:"finish_time"` // 完成执行时间, 单位 : ms
UsedTime int64 `json:"used_time"` // 执行耗时, 单位 : ms
Result string `json:"result"` // 执行结果
Command string `json:"command"` // 执行的命令
ArgList []string `json:"arg_list"` // 参数列表
Err error `json:"-"` // 失败信息
InstanceFlag string `json:"instance_flag"` // 实例标识
StartTime int64 `json:"start_time"` // 开始执行时间, 单位 : ms
FinishTime int64 `json:"finish_time"` // 完成执行时间, 单位 : ms
UsedTime int64 `json:"used_time"` // 执行耗时, 单位 : ms
Result string `json:"result"` // 执行结果
Command consts.RedisCmd `json:"command"` // 执行的命令
ArgList []string `json:"arg_list"` // 参数列表
Err error `json:"-"` // 失败信息
}

54
go.mod
View File

@ -1,60 +1,34 @@
module git.zhangdeman.cn/zhangdeman/redis
go 1.21
go 1.23.0
toolchain go1.21.5
toolchain go1.24.2
require (
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240617073616-39e82fd033ed
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20240308024848-54993a0ed4a6
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240618035451-8d48a6bd39dd
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250420101447-0b570213d5c7
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e
github.com/gin-gonic/gin v1.10.0
github.com/go-redis/redis/v8 v8.11.5
github.com/go-redis/redis_rate/v9 v9.1.2
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740
github.com/pkg/errors v0.9.1
github.com/redis/go-redis/v9 v9.7.3
go.uber.org/zap v1.27.0
gopkg.in/yaml.v3 v3.0.1
)
require (
github.com/BurntSushi/toml v1.4.0 // indirect
github.com/bytedance/sonic v1.11.8 // indirect
github.com/bytedance/sonic/loader v0.1.1 // indirect
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4 // indirect
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 // indirect
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd // indirect
github.com/BurntSushi/toml v1.5.0 // indirect
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect
github.com/chenzhuoyu/iasm v0.9.1 // indirect
github.com/cloudwego/base64x v0.1.4 // indirect
github.com/cloudwego/iasm v0.2.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect
github.com/gabriel-vasile/mimetype v1.4.4 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/go-ini/ini v1.67.0 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.22.0 // indirect
github.com/goccy/go-json v0.10.3 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/klauspost/cpuid/v2 v2.2.8 // indirect
github.com/leodido/go-urn v1.4.0 // indirect
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible // indirect
github.com/lestrrat-go/strftime v1.0.6 // indirect
github.com/mattn/go-isatty v0.0.20 // indirect
github.com/go-redis/redismock/v9 v9.2.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mozillazg/go-pinyin v0.20.0 // indirect
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
github.com/redis/go-redis/v9 v9.5.3 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.12 // indirect
github.com/tidwall/gjson v1.18.0 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.8.0 // indirect
golang.org/x/crypto v0.24.0 // indirect
golang.org/x/net v0.26.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
)

277
go.sum
View File

@ -1,256 +1,101 @@
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20230815040024-2b12dd51d19b h1:C7KftnLh7dOqzNRs5dn/9yqMDvuqMn5RCglvV6bY758=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20230815040024-2b12dd51d19b/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240104123641-b3f23974e5d6 h1:ytpXTP3oxp480BAZQoOzqlBP4XP73NcpMplZ1/fA1lQ=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240104123641-b3f23974e5d6/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240617073616-39e82fd033ed h1:BGv+y6ZdtkxI4HeSIHun0QRrIzjLnUht0bKdyO2t6n4=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240617073616-39e82fd033ed/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20230815124643-0c8a013bdbee h1:ItHGipuUOFfWpffpsdnZQryCH/simnHmTDuju+GYwaM=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20230815124643-0c8a013bdbee/go.mod h1:l9S40lsDnTd/VAZjh1kmfYvz0B9z+7oT86pMQ/KurWo=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20231224145141-489e31b07a71 h1:nvVSH+Ju8EmoPiPHTae5lxHo4kDjROYChs19Yayz+NY=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20231224145141-489e31b07a71/go.mod h1:SrtvrQRdzt+8KfYzvosH++gWxo2ShPTzR1m3VQ6uX7U=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240130062251-a87a97b0e8d4 h1:93JYY8JLbFcrlq37q/uKyxs2r2e3modsjvfSbnZQ/UI=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240130062251-a87a97b0e8d4/go.mod h1:SrtvrQRdzt+8KfYzvosH++gWxo2ShPTzR1m3VQ6uX7U=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240612081722-31c64d4d4ce7 h1:QR8vMXOTy0NFKdodsGKA4gTNHJMfob3yRFYMXrZj7ek=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240612081722-31c64d4d4ce7/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240924065029-c865046cd9e7 h1:tyCPCMK+68PZ0axZylQHitMVp1d5mzNr9/YqMHXqo+A=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20240924065029-c865046cd9e7/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241008084126-0b1c661317ee h1:4nuaCr5GQcx4z9/xWeEnjmLVV6J0j+QT68+AUKI9dFc=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241008084126-0b1c661317ee/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241009101340-1d415ef93cac h1:0V9ubWn7VLmefcPuuUfmmioNhdWQ9FeTXpwGCwbb3hE=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241009101340-1d415ef93cac/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241009101709-d8400fb206b4 h1:GUWgrIR7Gw1BIPzU6qUQgnB+7ZCE9nIwudAQTk7cyoU=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241009101709-d8400fb206b4/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125081557-cacc6b3cafc6 h1:f24T6CtVn8bF84fbXpWTzS47otE+U2IdBj3cZero+OQ=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20241125081557-cacc6b3cafc6/go.mod h1:IXXaZkb7vGzGnGM5RRWrASAuwrVSNxuoe0DmeXx5g6k=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250420100501-55e6ac5d835d h1:kWfJiJcJCaN3xEby1fepTg8Vy3umi7L54K/18on2bfw=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250420100501-55e6ac5d835d/go.mod h1:5p8CEKGBxi7qPtTXDI3HDmqKAfIm5i/aBWdrbkbdNjc=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250420101447-0b570213d5c7 h1:dmZ/mwRQ/AGlKXYWyk4Ci+KRiMcJwZii7nUCj2F2bpM=
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250420101447-0b570213d5c7/go.mod h1:5p8CEKGBxi7qPtTXDI3HDmqKAfIm5i/aBWdrbkbdNjc=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211 h1:I/wOsRpCSRkU9vo1u703slQsmK0wnNeZzsWQOGtIAG0=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20240311030808-e2a2e6a3c211/go.mod h1:SrtvrQRdzt+8KfYzvosH++gWxo2ShPTzR1m3VQ6uX7U=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20230815063108-532ea798c348 h1:AE5kwFlumnFLnLQ1RIClwGtM1LXKo9TLxMgyc/WJI78=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20230815063108-532ea798c348/go.mod h1:iVjdifEA/WPHsilfIp4jnDRM7w8ATGjlzMvsZhdtL1Y=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20231008133508-da9b21010445 h1:yBpL6QqC5e4LS5LZgwnjeanUmbJleeCwvZ344EpR5Vg=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20231008133508-da9b21010445/go.mod h1:qLJrvO4n5i0PjOCCcAQUMKDvsqf8QJRmMUDRk8yAw7g=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20240308024848-54993a0ed4a6 h1:KeRD+IMkzk5RcHyJijT7tLRKW4wtulGcpG1dkKSr/5A=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20240308024848-54993a0ed4a6/go.mod h1:IpTqawATar71MlLpheQAWrsXMqV2AxoZ3e0Vp3MeHNs=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20230815040629-5c584bcb7691 h1:Mdk0bAao3Plp7ck7WdnQE5WJkHjmHRw6N+jE4u/1jbQ=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20230815040629-5c584bcb7691/go.mod h1:UxkrpJIdDdgGkLsfmYVkUjGEFwbRkxbplWqUitpfca0=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20231224125439-01f39b6ea08d h1:TV0BCQQewBEtLsv3i9gXkxLFd5A5bWBTiNd3D/I5o4Q=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20231224125439-01f39b6ea08d/go.mod h1:w7kG4zyTJ1uPFaTWhze+OQuaUBINT2XnDxpyiM6ctc0=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240110090803-399e964daa0c h1:k7VCn9GfRGTilvdF/TcTFVMDBfKLe3VeGAtMTiDSnS0=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240110090803-399e964daa0c/go.mod h1:w7kG4zyTJ1uPFaTWhze+OQuaUBINT2XnDxpyiM6ctc0=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4 h1:s6d4b6yY+NaK1AzoBD1pxqsuygEHQz0Oie86c45geDw=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20241101082529-28a6c68e38a4/go.mod h1:V4Dfg1v/JVIZGEKCm6/aehs8hK+Xow1dkL1yiQymXlQ=
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0 h1:gUDlQMuJ4xNfP2Abl1Msmpa3fASLWYkNlqDFF/6GN0Y=
git.zhangdeman.cn/zhangdeman/op_type v0.0.0-20240122104027-4928421213c0/go.mod h1:VHb9qmhaPDAQDcS6vUiDCamYjZ4R5lD1XtVsh55KsMI=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240325080031-1f58204e8687 h1:uQcGqdzi4UdpZlp4f4FUPeBqoygP58pEKJkmN3ROsE0=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240325080031-1f58204e8687/go.mod h1:gf7SW2TXATgux8pfdFedMkXWv2515OtIIM/5c4atkFw=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240618035451-8d48a6bd39dd h1:2Y37waOVCmVvx0Rp8VGEptE2/2JVMImtxB4dKKDk/3w=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20240618035451-8d48a6bd39dd/go.mod h1:6+7whkCmb4sJDIfH3HxNuXRveaM0gCCNWd2uXZqNtIE=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20230815042559-b34984be7444 h1:JVp575weLUX4sfhgjjxotJPxfHio7Ua8KHH3LMRRs2E=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20230815042559-b34984be7444/go.mod h1:IqS3vAMyt1fVCWS7RqGeUw1EFnL/ruUMha45G2T+YNM=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20231014142840-445c6407db92 h1:p1GVRYJc3NNoZeLs4CukitAbM3O/ALNq3l31cnbBQDM=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20231014142840-445c6407db92/go.mod h1:6OBeuwKy2J1TjdAwStEyC6aYC3kStmJiCg1eFC7g0fk=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20231227095334-7eb5cdbf9253 h1:GO3oZa5a2sqwAzGcLDJtQzmshSWRmoP7IDS8bwFqvC4=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20231227095334-7eb5cdbf9253/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241125081853-2d10d261da4c h1:BLcVowYti2mhYHZLFykocmbMJDMvFVg4lmXjDajhjD0=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241125081853-2d10d261da4c/go.mod h1:+D6uPSljwHywjVY5WSBY4TRVMj26TN5f5cFGEYMldjs=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd h1:q7GG14qgXKB4MEXQFOe7/UYebsqMfPaSX80TcPdOosI=
git.zhangdeman.cn/zhangdeman/serialize v0.0.0-20241223084948-de2e49144fcd/go.mod h1:+D6uPSljwHywjVY5WSBY4TRVMj26TN5f5cFGEYMldjs=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e h1:Q973S6CcWr1ICZhFI1STFOJ+KUImCl2BaIXm6YppBqI=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e/go.mod h1:VpPjBlwz8U+OxZuxzHQBv1aEEZ3pStH6bZvT21ADEbI=
github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8=
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240612083858-8d056baada2e h1:+PeWa2QdYBWnL32CfAAgy0dlaRCVNmYZDH4q+9w7Gfg=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240612083858-8d056baada2e/go.mod h1:US/pcq2vstE3iyxIHf53w8IeXKkZys7bj/ozLWkRYeE=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240924063449-ef80c6cb79d1 h1:LYw8NJeWcOiyrGjH9weyxnaMit94MlIngL+uskbLjtw=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20240924063449-ef80c6cb79d1/go.mod h1:+2qNxuRsfyfOvXk9HNwn+CmyPmmhhrQm/eIi1FDU1jw=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20241125065949-2f87fe0cd90e h1:/N5yXmOEH7N/h4S6nv/6os8sRenh95BXogTZ2RJI950=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20241125065949-2f87fe0cd90e/go.mod h1:17TlhgwKTLQLIzYW/R6G39oN5FFPdsEEFDWniv+ovgA=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740 h1:zPUoylfJTbc0EcxW+NEzOTBmoeFZ2I/rLFBnEzxb4Wk=
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740/go.mod h1:1ct92dbVc49pmXusA/iGfcQUJzcYmJ+cjAhgc3sDv1I=
github.com/BurntSushi/toml v1.4.0 h1:kuoIxZQy2WRRk1pttg9asf+WVv6tWQuBNVmK8+nqPr0=
github.com/BurntSushi/toml v1.4.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
github.com/bytedance/sonic v1.10.0 h1:qtNZduETEIWJVIyDl01BeNxur2rW9OwTQ/yBqFRkKEk=
github.com/bytedance/sonic v1.10.0/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE=
github.com/bytedance/sonic v1.10.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/bytedance/sonic v1.11.2 h1:ywfwo0a/3j9HR8wsYGWsIWl2mvRsI950HyoxiBERw5A=
github.com/bytedance/sonic v1.11.2/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4=
github.com/bytedance/sonic v1.11.8 h1:Zw/j1KfiS+OYTi9lyB3bb0CFxPJVkM17k1wyDG32LRA=
github.com/bytedance/sonic v1.11.8/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4=
github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM=
github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU=
github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg=
github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394 h1:OYA+5W64v3OgClL+IrOD63t4i/RW7RqrAVl9LTZ9UqQ=
github.com/axgle/mahonia v0.0.0-20180208002826-3358181d7394/go.mod h1:Q8n74mJTIgjX4RBBcHnJ05h//6/k6foqmgE45jTQtxg=
github.com/bsm/ginkgo/v2 v2.12.0 h1:Ny8MWAHyOepLGlLKYmXG4IEkioBysk6GpaRTLC8zwWs=
github.com/bsm/ginkgo/v2 v2.12.0/go.mod h1:SwYbGRRDovPVboqFv0tPTcG1sN61LM1Z4ARdbAV9g4c=
github.com/bsm/gomega v1.27.10 h1:yeMWxP2pV2fG3FgAODIY8EiRE3dy0aeFYt4l7wh6yKA=
github.com/bsm/gomega v1.27.10/go.mod h1:JyEr/xRbxbtgWNi8tIEVPUYZ5Dzef52k01W3YH0H+O0=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0=
github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpVsBuRksnlj1mLy4AWzRNQYxauNi62uWcE3to6eA=
github.com/chenzhuoyu/iasm v0.9.0 h1:9fhXjVzq5hUy2gkhhgHl95zG2cEAhw9OSGs8toWWAwo=
github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0=
github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog=
github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y=
github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w=
github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg=
github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
github.com/gabriel-vasile/mimetype v1.4.3 h1:in2uUcidCuFcDKtdcBxlR0rJ1+fsokWf+uqxgUFjbI0=
github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk=
github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I=
github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU=
github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y=
github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.15.0 h1:nDU5XeOKtB3GEa+uB7GNYwhVKsgjAR7VgKoNB6ryXfw=
github.com/go-playground/validator/v10 v10.15.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-playground/validator/v10 v10.16.0 h1:x+plE831WK4vaKHO/jpgUGsvLKIqRRkz6M78GuJAfGE=
github.com/go-playground/validator/v10 v10.16.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4=
github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-playground/validator/v10 v10.22.0 h1:k6HsTZ0sTnROkhS//R0O+55JgM8C4Bx7ia+JlgcnOao=
github.com/go-playground/validator/v10 v10.22.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM=
github.com/go-redis/redis/v8 v8.11.5 h1:AcZZR7igkdvfVmQTPnu9WE37LRrO/YrBH5zWyjDC0oI=
github.com/go-redis/redis/v8 v8.11.5/go.mod h1:gREzHqY1hg6oD9ngVRbLStwAWKhA0FEgq8Jd4h5lpwo=
github.com/go-redis/redis_rate/v9 v9.1.2 h1:H0l5VzoAtOE6ydd38j8MCq3ABlGLnvvbA1xDSVVCHgQ=
github.com/go-redis/redis_rate/v9 v9.1.2/go.mod h1:oam2de2apSgRG8aJzwJddXbNu91Iyz1m8IKJE2vpvlQ=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA=
github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQymUhg=
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/klauspost/cpuid/v2 v2.2.8 h1:+StwCXwm9PdpiEkPyzBXIy+M9KUb4ODm0Zarf1kS5BM=
github.com/klauspost/cpuid/v2 v2.2.8/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
github.com/knz/go-libedit v1.10.1/go.mod h1:MZTVkCWyz0oBc7JOWP3wNAzd002ZbM/5hgShxwh4x8M=
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8=
github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is=
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4=
github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA=
github.com/lestrrat-go/strftime v1.0.6 h1:CFGsDEt1pOpFNU+TJB0nhz9jl+K0hZSLE205AhTIGQQ=
github.com/lestrrat-go/strftime v1.0.6/go.mod h1:f7jQKgV5nnJpYgdEasS+/y7EsTb8ykN2z68n3TtcTaw=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/go-redis/redismock/v9 v9.2.0 h1:ZrMYQeKPECZPjOj5u9eyOjg8Nnb0BS9lkVIZ6IpsKLw=
github.com/go-redis/redismock/v9 v9.2.0/go.mod h1:18KHfGDK4Y6c2R0H38EUGWAdc7ZQS9gfYxc94k7rWT0=
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mozillazg/go-pinyin v0.20.0 h1:BtR3DsxpApHfKReaPO1fCqF4pThRwH9uwvXzm+GnMFQ=
github.com/mozillazg/go-pinyin v0.20.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/pelletier/go-toml/v2 v2.0.9 h1:uH2qQXheeefCCkuBBSLi7jCiSmj3VRh2+Goq2N7Xxu0=
github.com/pelletier/go-toml/v2 v2.0.9/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pelletier/go-toml/v2 v2.1.1 h1:LWAJwfNvjQZCFIDKWYQaM62NcYeYViCmWIwmOStowAI=
github.com/pelletier/go-toml/v2 v2.1.1/go.mod h1:tJU2Z3ZkXwnxa4DPO899bsyIoywizdUvyaeZurnPPDc=
github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM=
github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/redis/go-redis/v9 v9.5.3 h1:fOAp1/uJG+ZtcITgZOfYFmTKPE7n4Vclj1wZFgRciUU=
github.com/redis/go-redis/v9 v9.5.3/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M=
github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4=
github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA=
github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa9E=
github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE=
github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk=
github.com/tidwall/gjson v1.16.0 h1:SyXa+dsSPpUlcwEDuKuEBJEz5vzTvOea+9rjyYodQFg=
github.com/tidwall/gjson v1.16.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c=
go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk=
go.uber.org/zap v1.26.0 h1:sI7k6L95XOKS281NhVKOFCUNIvv9e0w4BF8N3u+tCRo=
go.uber.org/zap v1.26.0/go.mod h1:dtElttAiwGvoJ/vj4IwHBS/gXsEu/pZ50mUIRWuG0so=
go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.4.0 h1:A8WCeEWhLwPBKNbFi5Wv5UTCBx5zzubnXDlMOFAzFMc=
golang.org/x/arch v0.4.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.6.0 h1:S0JTfE48HbRj80+4tbvZDYsJ3tGv6BUU3XxyZ7CirAc=
golang.org/x/arch v0.6.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc=
golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc=
golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys=
golang.org/x/crypto v0.12.0 h1:tFM/ta59kqch6LlvYnPa0yx5a83cL2nHflFhYKvv9Yk=
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
golang.org/x/crypto v0.24.0 h1:mnl8DM0o513X8fdIkmyFE/5hTYxbwYOjDS/+rK6qpRI=
golang.org/x/crypto v0.24.0/go.mod h1:Z1PMYSOR5nyMcyAVAIQSKCDwalqy85Aqn1x3Ws4L5DM=
golang.org/x/net v0.14.0 h1:BONx9s002vGdD9umnlX1Po8vOZmrgH34qlHcD1MfK14=
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.11.0 h1:eG7RXZHdqOJ1i+0lgLgCpSXAp6M3LYlAo6osgSi0xOM=
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.12.0 h1:k+n5B8goJNdU7hSvEtMUz3d1Q6D/XW4COJSJR6fN0mc=
golang.org/x/text v0.12.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI=
google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
google.golang.org/protobuf v1.34.2 h1:6xV6lTsCfpGD21XK49h7MhtcApnLqkfYgPcdHftf6hg=
google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
nullprogram.com/x/optparse v1.0.0/go.mod h1:KdyPE+Igbe0jQUrVfMqDMeJQIJZEuyV7pjYmp6pbG50=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=

View File

@ -12,10 +12,9 @@ import (
"strings"
"git.zhangdeman.cn/zhangdeman/util"
redisClient "github.com/redis/go-redis/v9"
yml "gopkg.in/yaml.v3"
"github.com/go-redis/redis/v8"
)
// GetRedisServerInfo 获取 redis server info
@ -23,7 +22,7 @@ import (
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:24 下午 2021/11/27
func GetRedisServerInfo(client *redis.Client) (*ServerInfo, error) {
func GetRedisServerInfo(client *redisClient.ClusterClient) (*ServerInfo, error) {
var result ServerInfo
if err := infoToStruct(client, "server", &result); nil != err {
return nil, err
@ -36,7 +35,7 @@ func GetRedisServerInfo(client *redis.Client) (*ServerInfo, error) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:59 下午 2021/11/27
func GetMemoryInfo(client *redis.Client) (*MemoryInfo, error) {
func GetMemoryInfo(client *redisClient.ClusterClient) (*MemoryInfo, error) {
var result MemoryInfo
if err := infoToStruct(client, "memory", &result); nil != err {
return nil, err
@ -49,7 +48,7 @@ func GetMemoryInfo(client *redis.Client) (*MemoryInfo, error) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 1:10 下午 2021/11/27
func GetClientInfo(client *redis.Client) (*ClientInfo, error) {
func GetClientInfo(client *redisClient.ClusterClient) (*ClientInfo, error) {
var result ClientInfo
if err := infoToStruct(client, "clients", &result); nil != err {
return nil, err
@ -62,7 +61,7 @@ func GetClientInfo(client *redis.Client) (*ClientInfo, error) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 1:11 下午 2021/11/27
func GetPersistence(client *redis.Client) (*Persistence, error) {
func GetPersistence(client *redisClient.ClusterClient) (*Persistence, error) {
var result Persistence
if err := infoToStruct(client, "persistence", &result); nil != err {
return nil, err
@ -75,7 +74,7 @@ func GetPersistence(client *redis.Client) (*Persistence, error) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 1:19 下午 2021/11/27
func GetStats(client *redis.Client) (*Stats, error) {
func GetStats(client *redisClient.ClusterClient) (*Stats, error) {
var result Stats
if err := infoToStruct(client, "stats", &result); nil != err {
return nil, err
@ -88,7 +87,7 @@ func GetStats(client *redis.Client) (*Stats, error) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 1:23 下午 2021/11/27
func GetReplication(client *redis.Client) (*Replication, error) {
func GetReplication(client *redisClient.ClusterClient) (*Replication, error) {
var result Replication
if err := infoToStruct(client, "replication", &result); nil != err {
return nil, err
@ -102,7 +101,7 @@ func GetReplication(client *redis.Client) (*Replication, error) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 4:26 下午 2021/11/27
func GetSlaveList(client *redis.Client) []SlaveNode {
func GetSlaveList(client *redisClient.ClusterClient) []SlaveNode {
// 解析从库信息
slaveList := make([]SlaveNode, 0)
var data map[string]string
@ -160,7 +159,7 @@ func GetSlaveList(client *redis.Client) []SlaveNode {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 1:24 下午 2021/11/27
func GetCPUInfo(client *redis.Client) (*CPU, error) {
func GetCPUInfo(client *redisClient.ClusterClient) (*CPU, error) {
var result CPU
if err := infoToStruct(client, "cpu", &result); nil != err {
return nil, err
@ -173,7 +172,7 @@ func GetCPUInfo(client *redis.Client) (*CPU, error) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 1:27 下午 2021/11/27
func GetCommandStats(client *redis.Client) (*Stats, error) {
func GetCommandStats(client *redisClient.ClusterClient) (*Stats, error) {
var result Stats
if err := infoToStruct(client, "stats", &result); nil != err {
return nil, err
@ -186,7 +185,7 @@ func GetCommandStats(client *redis.Client) (*Stats, error) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 1:32 下午 2021/11/27
func GetCommandInfo(client *redis.Client) ([]CmdStat, error) {
func GetCommandInfo(client *redisClient.ClusterClient) ([]CmdStat, error) {
var result map[string]string
if err := infoToStruct(client, "commandstats", &result); nil != err {
return make([]CmdStat, 0), err
@ -237,7 +236,7 @@ func GetCommandInfo(client *redis.Client) ([]CmdStat, error) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2:44 下午 2021/11/27
func GetKeyspace(client *redis.Client) ([]DB, error) {
func GetKeyspace(client *redisClient.ClusterClient) ([]DB, error) {
var result map[string]string
if err := infoToStruct(client, "keyspace", &result); nil != err {
return make([]DB, 0), err
@ -278,7 +277,7 @@ func GetKeyspace(client *redis.Client) ([]DB, error) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:30 下午 2021/11/27
func GetCluster(client *redis.Client) (*Cluster, error) {
func GetCluster(client *redisClient.ClusterClient) (*Cluster, error) {
var result Cluster
if err := infoToStruct(client, "cluster", &result); nil != err {
return nil, err
@ -291,7 +290,7 @@ func GetCluster(client *redis.Client) (*Cluster, error) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 3:35 下午 2021/11/27
func GetErrorStats(client *redis.Client) ([]Error, error) {
func GetErrorStats(client *redisClient.ClusterClient) ([]Error, error) {
var result map[string]string
if err := infoToStruct(client, "errorstats", &result); nil != err {
return make([]Error, 0), err
@ -318,7 +317,7 @@ func GetErrorStats(client *redis.Client) ([]Error, error) {
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:28 下午 2021/11/27
func infoToStruct(client *redis.Client, module string, receiver interface{}) error {
func infoToStruct(client *redisClient.ClusterClient, module string, receiver interface{}) error {
data := client.Info(context.Background(), module).String()
// yaml 文件规范要求, key: val , 注意 : 的后面有空格
data = strings.ReplaceAll(data, ":", ": ")

View File

@ -1,98 +0,0 @@
// Package rate_limit ...
//
// Description : rate_limit ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2023-03-09 11:31
package rate_limit
import (
"context"
"time"
redisInstance "github.com/go-redis/redis/v8"
"github.com/go-redis/redis_rate/v9"
)
var (
// limiter 限流实例
limiter *redis_rate.Limiter
)
// InitLimiter 初始化限流器实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:40 2023/3/9
func InitLimiter(redisClient *redisInstance.Client) {
limiter = redis_rate.NewLimiter(redisClient)
}
// Second 每秒允许的访问数
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:42 2023/3/9
func Second(ctx context.Context, key string, total, rate int) (bool, error) {
if total <= 0 || rate <= 0 {
return true, nil
}
res, err := limiter.AllowN(ctx, key, redis_rate.PerSecond(total), rate)
if nil != err {
return false, err
}
return res.Allowed > 0, nil
}
// Minute 每分钟允许访问数
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:46 2023/3/9
func Minute(ctx context.Context, key string, total, rate int) (bool, error) {
if total <= 0 || rate <= 0 {
return true, nil
}
res, err := limiter.AllowN(ctx, key, redis_rate.PerMinute(total), rate)
if nil != err {
return false, err
}
return res.Allowed > 0, nil
}
// Hour 每小时允许访问数
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:47 2023/3/9
func Hour(ctx context.Context, key string, total, rate int) (bool, error) {
if total <= 0 || rate <= 0 {
return true, nil
}
res, err := limiter.AllowN(ctx, key, redis_rate.PerHour(total), rate)
if nil != err {
return false, err
}
return res.Allowed > 0, nil
}
// Day 每天允许访问数
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 11:47 2023/3/9
func Day(ctx context.Context, key string, total, rate int) (bool, error) {
if total <= 0 || rate <= 0 {
return true, nil
}
res, err := limiter.AllowN(ctx, key, redis_rate.Limit{
Rate: rate,
Period: 24 * time.Hour,
Burst: total,
}, rate)
if nil != err {
return false, err
}
return res.Allowed > 0, nil
}

View File

@ -9,6 +9,7 @@ package redis
import (
"context"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/redis/define"
"strings"
"time"
@ -26,13 +27,31 @@ var (
type wrapper struct {
}
// Exist 缓存Key是否存在
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 12:31 2024/6/21
func (w *wrapper) Exist(ctx context.Context, instanceFlag string, key string) *define.RedisResult {
return Client.Exec(ctx, instanceFlag, consts.RedisCommandExists, key)
}
// TTL ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 18:14 2024/10/9
func (w *wrapper) TTL(ctx context.Context, instanceFlag string, key string) *define.RedisResult {
return Client.Exec(ctx, instanceFlag, consts.RedisCommandTTL, key)
}
// Get Get命令
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:17 2024/6/19
func (w *wrapper) Get(ctx context.Context, instanceFlag string, key string) *define.RedisResult {
return Client.Exec(ctx, instanceFlag, "GET", key)
return Client.Exec(ctx, instanceFlag, consts.RedisCommandGet, key)
}
// Del 删除命令
@ -41,7 +60,7 @@ func (w *wrapper) Get(ctx context.Context, instanceFlag string, key string) *def
//
// Date : 16:19 2024/6/19
func (w *wrapper) Del(ctx context.Context, instanceFlag string, keyList ...string) *define.RedisResult {
return Client.Exec(ctx, instanceFlag, "DEL", strings.Join(keyList, " "))
return Client.Exec(ctx, instanceFlag, consts.RedisCommandDel, strings.Join(keyList, " "))
}
// SetEx 设置数据并且带有效期, 有效期单位 : s
@ -56,9 +75,9 @@ func (w *wrapper) SetEx(ctx context.Context, instanceFlag string, key string, va
ttl = ttl - now
}
if withLock {
return Client.Exec(ctx, instanceFlag, "SET", key, value, "EX", ttl, "NX")
return Client.Exec(ctx, instanceFlag, consts.RedisCommandSet, key, value, "EX", ttl, "NX")
}
return Client.Exec(ctx, instanceFlag, "SET", key, value, "EX", ttl)
return Client.Exec(ctx, instanceFlag, consts.RedisCommandSet, key, value, "EX", ttl)
}
// LPop ...
@ -67,7 +86,7 @@ func (w *wrapper) SetEx(ctx context.Context, instanceFlag string, key string, va
//
// Date : 16:29 2024/6/19
func (w *wrapper) LPop(ctx context.Context, instanceFlag string, key string) *define.RedisResult {
return Client.Exec(ctx, instanceFlag, "LPOP", key)
return Client.Exec(ctx, instanceFlag, consts.RedisCommandLpop, key)
}
// RPop ...
@ -76,7 +95,7 @@ func (w *wrapper) LPop(ctx context.Context, instanceFlag string, key string) *de
//
// Date : 16:30 2024/6/19
func (w *wrapper) RPop(ctx context.Context, instanceFlag string, key string) *define.RedisResult {
return Client.Exec(ctx, instanceFlag, "RPOP", key)
return Client.Exec(ctx, instanceFlag, consts.RedisCommandRpop, key)
}
// LPush ...
@ -85,7 +104,7 @@ func (w *wrapper) RPop(ctx context.Context, instanceFlag string, key string) *de
//
// Date : 16:31 2024/6/19
func (w *wrapper) LPush(ctx context.Context, instanceFlag string, key string, value string) *define.RedisResult {
return Client.Exec(ctx, instanceFlag, "LPUSH", key, value)
return Client.Exec(ctx, instanceFlag, consts.RedisCommandLpush, key, value)
}
// RPush ...
@ -94,7 +113,7 @@ func (w *wrapper) LPush(ctx context.Context, instanceFlag string, key string, va
//
// Date : 16:31 2024/6/19
func (w *wrapper) RPush(ctx context.Context, instanceFlag string, key string, value string) *define.RedisResult {
return Client.Exec(ctx, instanceFlag, "RPUSH", key, value)
return Client.Exec(ctx, instanceFlag, consts.RedisCommandRpush, key, value)
}
// HGet ...
@ -103,7 +122,7 @@ func (w *wrapper) RPush(ctx context.Context, instanceFlag string, key string, va
//
// Date : 16:33 2024/6/19
func (w *wrapper) HGet(ctx context.Context, instanceFlag string, key string, field string) *define.RedisResult {
return Client.Exec(ctx, instanceFlag, "HGET", key, field)
return Client.Exec(ctx, instanceFlag, consts.RedisCommandHget, key, field)
}
// HSet ...
@ -112,7 +131,7 @@ func (w *wrapper) HGet(ctx context.Context, instanceFlag string, key string, fie
//
// Date : 16:33 2024/6/19
func (w *wrapper) HSet(ctx context.Context, instanceFlag string, key string, field string, value string) *define.RedisResult {
return Client.Exec(ctx, instanceFlag, "HSET", key, field, value)
return Client.Exec(ctx, instanceFlag, consts.RedisCommandHset, key, field, value)
}
// HDel ...
@ -121,5 +140,5 @@ func (w *wrapper) HSet(ctx context.Context, instanceFlag string, key string, fie
//
// Date : 16:37 2024/6/19
func (w *wrapper) HDel(ctx context.Context, instanceFlag string, key string, fieldList ...string) *define.RedisResult {
return Client.Exec(ctx, instanceFlag, "HSET", key, strings.Join(fieldList, " "))
return Client.Exec(ctx, instanceFlag, consts.RedisCommandHdel, key, strings.Join(fieldList, " "))
}