Compare commits

..

37 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
ec5d33743d Merge pull request '升级redis基础库' (#2) from feature/upgrade_client into master
Reviewed-on: #2
2024-06-19 20:55:15 +08:00
1a4ce91fb5 包装redis常用命令 2024-06-19 16:39:16 +08:00
11ac38fe69 升级redis client实现 2024-06-19 16:13:06 +08:00
1b27f6ae36 增加Redis配置 + 接口定义 2024-06-19 10:24:51 +08:00
929fab208a fix Error 2024-06-18 15:04:38 +08:00
2084fdaecb update go mod 2024-06-18 14:34:59 +08:00
7c953a89af update go mod 2024-03-08 10:48:04 +08:00
7e99499532 upgrade go mod 2023-12-24 22:56:32 +08:00
6783a2a1d0 修复锁未初始化BUG 2023-08-17 10:38:33 +08:00
eaf61d85df 优化redis client 2023-08-16 11:55:04 +08:00
4e00c367d5 update go mod 2023-08-16 11:33:55 +08:00
c17b875c9f 切换序列化库 2023-08-11 14:08:30 +08:00
5164125ff4 升级redis初始化 2023-03-09 18:16:23 +08:00
4a418d1d41 增加redis连接初始化 2023-03-09 18:11:17 +08:00
eeed66642e Merge pull request '支持基于redis的流量控制' (#1) from feature/rate_limit into master
Reviewed-on: #1
2023-03-09 14:06:42 +08:00
13 changed files with 633 additions and 1141 deletions

33
abstract/IRedisClient.go Normal file
View File

@ -0,0 +1,33 @@
// Package abstract ...
//
// Description : abstract ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-06-18 15:09
package abstract
import (
"context"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/redis/define"
"github.com/go-redis/redismock/v9"
"go.uber.org/zap"
)
// IRedisClient redis客户端定义
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 15:09 2024/6/18
type IRedisClient interface {
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.GetRedisClient(ctx.Flag); nil != err {
return err
}
return rc.Master.Set(nil, key, value, -1).Err()
}

575
client.go
View File

@ -8,369 +8,274 @@
package redis
import (
"encoding/json"
"fmt"
"path/filepath"
"context"
"git.zhangdeman.cn/zhangdeman/consts"
"github.com/go-redis/redismock/v9"
"strings"
"sync"
"time"
"git.zhangdeman.cn/zhangdeman/util"
"git.zhangdeman.cn/zhangdeman/logger"
redisInstance "github.com/go-redis/redis/v8"
"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 连接实例
Client ClientInterface
Client abstract.IRedisClient
)
// InitWithCfgFile 使用配置文件初始化
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:24 2022/6/22
func InitWithCfgFile(cfgFilePath string) error {
c := &OwnClient{
lock: &sync.RWMutex{},
instanceTable: make(map[string]*RealClient),
confTable: make(map[string]*FullConfig),
parseErrorFunc: defaultParseError,
func init() {
Client = &OwnClient{
lock: &sync.RWMutex{},
instanceTable: make(map[string]*define.ClientInfo),
whiteCommandTable: make(map[string]bool),
}
if err := c.loadConfig(cfgFilePath); nil != err {
return err
}
Client = c
return nil
}
// InitWithCfgDir 使用配置目录初始化
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:31 2022/6/22
func InitWithCfgDir(cfgDir string) error {
c := &OwnClient{
lock: &sync.RWMutex{},
instanceTable: make(map[string]*RealClient),
confTable: make(map[string]*FullConfig),
parseErrorFunc: defaultParseError,
}
if err := c.batchLoadConfig(cfgDir); nil != err {
return err
}
Client = c
return nil
}
// InitWithCfgFileList 使用批量的配置文件初始化
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 21:33 2022/6/22
func InitWithCfgFileList(cfgFileList []string) error {
c := &OwnClient{
lock: &sync.RWMutex{},
instanceTable: make(map[string]*RealClient),
confTable: make(map[string]*FullConfig),
parseErrorFunc: defaultParseError,
}
for _, cfgFilePath := range cfgFileList {
if err := c.loadConfig(cfgFilePath); nil != err {
return err
}
}
Client = c
return nil
}
// defaultParseError ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:59 下午 2021/2/27
func defaultParseError(err error) error {
if nil == err {
return nil
}
errMsg := err.Error()
if errMsg == "nil" || errMsg == "<nil>" {
return nil
}
strArr := strings.Split(errMsg, ":")
if len(strArr) != 2 {
return err
}
msg := strings.ToLower(strings.TrimSpace(strArr[1]))
if msg == "nil" || msg == "<nil>" {
return nil
}
return err
}
// RealClient 包装好的 redis client
type RealClient struct {
Flag string // redis 标识
Master *redisInstance.Client // redis 实例
Slave *redisInstance.Client // redis 实例
Logger *zap.Logger // 日志实例
}
// NewClient 获取redis client实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 5:05 下午 2021/2/27
func NewClient(config map[string]*FullConfig, parseErrorFunc func(err error) error) (ClientInterface, error) {
c := &OwnClient{
instanceTable: make(map[string]*RealClient),
loggerTable: make(map[string]*zap.Logger),
confTable: config,
parseErrorFunc: parseErrorFunc,
}
if nil == c.parseErrorFunc {
c.parseErrorFunc = defaultParseError
}
return c, c.init()
}
// OwnClient 包装的redis client
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 4:52 下午 2021/2/27
type OwnClient struct {
lock *sync.RWMutex // 锁
loggerTable map[string]*zap.Logger // 日志实例
instanceTable map[string]*RealClient // redis 实例
confTable map[string]*FullConfig // redis 配置
parseErrorFunc func(err error) error // 解析err的function,解析执行结果是否为失败,有的场景,执行成功,返回 redis:nil / redis:<nil>
lock *sync.RWMutex
instanceTable map[string]*define.ClientInfo
whiteCommandTable map[string]bool
logger *zap.Logger
extraLogFieldList []string
mockMode bool
mockInstance redismock.ClientMock
mockClient *redisClient.Client
}
// AddClientWithCfgFile 使用具体配置文件初始化
func (o *OwnClient) isAllowCommand(command string) bool {
if len(o.whiteCommandTable) == 0 {
// 未配置, 视为全部允许执行
return true
}
if o.whiteCommandTable["*"] {
// 配置了 * 视为全部允许执行
return true
}
command = strings.ToLower(strings.TrimSpace(command))
o.lock.RLock()
defer o.lock.RUnlock()
return o.whiteCommandTable[command]
}
// Exec 执行命令
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:57 2022/6/15
func (c *OwnClient) AddClientWithCfgFile(cfgPath string) error {
var (
err error
)
if err = c.loadConfig(cfgPath); nil != err {
return err
}
return c.init()
}
// AddClientWithCfgDir 使用配置目录进行初始化
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 20:58 2022/6/15
func (c *OwnClient) AddClientWithCfgDir(cfgDir string) error {
var (
err error
)
if err = c.batchLoadConfig(cfgDir); nil != err {
return err
}
return c.init()
}
// loadConfig 载入配置文件
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 14:31 2022/6/15
func (c *OwnClient) loadConfig(cfgPath string) error {
var (
err error
cfg FullConfig
)
filePathArr := strings.Split(cfgPath, string(filepath.Separator))
if len(filePathArr) == 0 {
return CfgFilePathError()
}
fileName := strings.ToLower(filePathArr[len(filePathArr)-1])
fileArr := strings.Split(fileName, ".")
if len(filePathArr) < 2 {
return CfgFileFormatErr("未知")
}
flag := strings.Trim(
strings.Trim(
strings.Trim(fileName, ".json"),
".yaml"), ".yml")
switch strings.ToLower(fileArr[len(fileArr)-1]) {
case "json":
if err = util.File.ReadJSONContent(cfgPath, &cfg); nil != err {
return err
}
flag = strings.Join(fileArr[0:len(fileArr)-1], ".")
case "yml":
fallthrough
case "yaml":
if err = util.File.ReadYmlContent(cfgPath, &cfg); nil != err {
return err
}
flag = strings.Join(fileArr[0:len(fileArr)-1], ".")
default:
// 不支持的格式,跳过
}
c.lock.Lock()
c.confTable[flag] = &cfg
c.lock.Unlock()
return nil
}
// batchLoadConfig 批量载入配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:44 2022/6/15
func (c *OwnClient) batchLoadConfig(cfgDir string) error {
filepathNames, _ := filepath.Glob(filepath.Join(cfgDir, "*"))
for i := range filepathNames {
if err := c.loadConfig(filepathNames[i]); nil != err {
return err
}
}
return nil
}
// init 初始化redis连接
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 5:31 下午 2021/2/27
func (c *OwnClient) init() error {
var err error
for flag, conf := range c.confTable {
c.instanceTable[flag] = &RealClient{
Flag: flag,
Master: redisInstance.NewClient(Config2Options(conf.Master)),
Slave: redisInstance.NewClient(Config2Options(conf.Slave)),
}
if c.instanceTable[flag].Logger, err = logger.GetLogInstanceFromInputConfig(conf.Logger); nil != err {
return InitLoggerErr(flag, err)
}
}
return nil
}
// initLogger 初始化日志
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 7:07 下午 2021/2/27
func (c *OwnClient) initLogger(flag string, conf *logger.InputLogConfig) error {
var err error
c.loggerTable[flag], err = logger.GetLogInstanceFromInputConfig(conf)
return LoggerInitFail(flag, err)
}
// GetRedisClient 获取redis实例
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 5:16 下午 2021/2/27
func (c *OwnClient) GetRedisClient(flag string) (*RealClient, error) {
redisClient, exist := c.instanceTable[flag]
if !exist {
return nil, FlagNotFound(flag)
}
return redisClient, nil
}
// log 记录redis请求日志
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 8:52 下午 2021/2/27
func (c *OwnClient) log(ctx *Context, realClient *RealClient, isMaster bool, cmdResult redisInstance.Cmder, startTime int64, finishTime int64) {
if nil == realClient || nil == realClient.Logger {
return
}
realClient.Logger.Info(
"执行redis命令日志记录",
zap.Any(ctx.RequestIDField, ctx.RequestID), // 上下文串联的requestID
zap.String("instance_flag", ctx.Flag), // redis 实例的标识
zap.Any("exec_command_name", cmdResult.Name()), // 执行的命令
zap.Any("exec_command_arg", cmdResult.Args()), // 执行的命令参数
zap.Bool("use_master", isMaster), // 是否使用主节点
zap.Float64("exec_used_time", float64(finishTime-startTime)/1e6), // 耗时,单位: ms
zap.Error(cmdResult.Err()), // 异常信息
zap.String("command_result", cmdResult.String()), // 命令执行后的结果
)
}
// CommandProxy 执行命令的代理
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 9:41 下午 2021/2/27
func (c *OwnClient) CommandProxy(ctx *Context, flag string, cmd string, param ...interface{}) (string, error) {
var (
realClient *RealClient
err error
)
if len(cmd) == 0 {
return "", EmptyCmd()
}
// Date : 11:05 2024/6/19
func (o *OwnClient) Exec(ctx context.Context, instanceFlag string, command consts.RedisCmd, args ...any) *define.RedisResult {
if nil == ctx {
ctx = NewContext(flag)
}
if realClient, err = c.GetRedisClient(ctx.Flag); nil != err {
return "", err
}
flagArr := strings.Split(flag, "#")
if len(flagArr) == 1 {
flagArr = append(flagArr, "r")
}
isMater := flagArr[1] == "w"
redisClient := realClient.Slave
if isMater {
redisClient = realClient.Master
}
redisCmd := append([]interface{}{cmd}, param...)
startTime := time.Now().Unix()
cmdResult := redisClient.Do(ctx.Ctx, redisCmd...)
go c.log(ctx, realClient, isMater, cmdResult, startTime, time.Now().UnixNano())
return fmt.Sprintf("%v", cmdResult.Val()), c.parseErrorFunc(cmdResult.Err())
}
// CommandProxyWithReceiver 执行命令,并解析结果
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:00 下午 2021/2/27
func (c *OwnClient) CommandProxyWithReceiver(ctx *Context, flag string, receiver interface{}, cmd string, param ...interface{}) error {
if nil == receiver {
return ReceiverISNIL()
ctx = context.Background()
}
var (
err error
result string
instance *define.ClientInfo
)
if result, err = c.CommandProxy(ctx, flag, cmd, param...); nil != err {
return err
cmdParamList := []any{
strings.ToLower(command.String()), // redis 命令不区分大小写, 统一使用小写
}
return ResultConvertFail(json.Unmarshal([]byte(result), receiver))
argStrList := make([]string, 0)
for _, itemArg := range args {
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,
InstanceFlag: instanceFlag,
}
defer func() {
res.FinishTime = time.Now().UnixMilli()
res.UsedTime = res.FinishTime - res.StartTime
if nil == o.logger {
// 未注入日志实例
return
}
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.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 {
return res
}
if nil == ctx {
ctx = context.Background()
}
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 = wrapperOperate.AnyDataType(cmdRes.Val()).ToString().Value()
return res
}
// ClientInterface 定义redis client的接口实现,方便单元测试数据mock
// SetCommandWhiteList 设置命令白名单, 空 或者 包含 * 则认为所有命令均允许执行
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 10:49 下午 2021/2/27
type ClientInterface interface {
GetRedisClient(flag string) (*RealClient, error)
CommandProxy(ctx *Context, flag string, cmd string, param ...interface{}) (string, error)
CommandProxyWithReceiver(ctx *Context, flag string, receiver interface{}, cmd string, param ...interface{}) error
// Date : 11:02 2024/6/19
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.String()))] = true
}
}
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) (*define.ClientInfo, error) {
o.lock.RLock()
defer o.lock.RUnlock()
instance, exist := o.instanceTable[instanceFlag]
if !exist {
return nil, errors.New(instanceFlag + " : redis instance is not found")
}
return instance, nil
}
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] = clientInfo
return nil
}
func (o *OwnClient) RemoveClient(instanceFlag string) {
o.lock.Lock()
defer o.lock.Unlock()
delete(o.instanceTable, instanceFlag)
}
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(true)
}
// 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
}
}

78
define/config.go Normal file
View File

@ -0,0 +1,78 @@
// Package define ...
//
// Description : define ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-06-18 16:12
package define
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.
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"` // 集群名称
Protocol int
Username string `json:"username" yaml:"username" ini:"username" toml:"username"`
Password string `json:"password" yaml:"password" ini:"password" toml:"password"`
MaxRetries int `json:"max_retries" yaml:"max_retries" ini:"max_retries" toml:"max_retries"`
MinRetryBackoff int `json:"min_retry_backoff" yaml:"min_retry_backoff" ini:"min_retry_backoff" toml:"min_retry_backoff"` // 最小重试间隔,单位 : ms
MaxRetryBackoff int `json:"max_retry_backoff" yaml:"max_retry_backoff" ini:"max_retry_backoff" toml:"max_retry_backoff"` // 最大重试时间间隔, 单位 : ms
DialTimeout int `json:"dial_timeout" yaml:"dial_timeout" ini:"dial_timeout" toml:"dial_timeout"` // 连接超时时间
ReadTimeout int `json:"read_timeout" yaml:"read_timeout" ini:"read_timeout" toml:"read_timeout"` // 读取超时时间
WriteTimeout int `json:"write_timeout" yaml:"write_timeout" ini:"write_timeout" toml:"write_timeout"` // 写入超时时间
ContextTimeoutEnabled bool `json:"context_timeout_enabled" yaml:"context_timeout_enabled" ini:"context_timeout_enabled" toml:"context_timeout_enabled"`
PoolFIFO bool `json:"pool_fifo" yaml:"pool_fifo" ini:"pool_fifo" toml:"pool_fifo"`
PoolSize int `json:"pool_size" yaml:"pool_size" ini:"pool_size" toml:"pool_size"` // applies per cluster node and not for the whole cluster
PoolTimeout int `json:"pool_timeout" yaml:"pool_timeout" ini:"pool_timeout" toml:"pool_timeout"` // 单位 : ms
MinIdleConn int `json:"min_idle_conn" yaml:"min_idle_conn" ini:"min_idle_conn" toml:"min_idle_conn"` // 最小空闲连接数
MaxIdleConn int `json:"max_idle_conn" yaml:"max_idle_conn" ini:"max_idle_conn" toml:"max_idle_conn"` // 最大空闲连接数
MaxActiveConn int `json:"max_active_conn" yaml:"max_active_conn" ini:"max_active_conn" toml:"max_active_conn"` // applies per cluster node and not for the whole cluster
ConnMaxIdleTime int `json:"conn_max_idle_time" yaml:"conn_max_idle_time" ini:"conn_max_idle_time" toml:"conn_max_idle_time"` // 连接最大空闲时长, 单位 : s
ConnMaxLifetime int `json:"conn_max_lifetime" yaml:"conn_max_lifetime" ini:"conn_max_lifetime" toml:"conn_max_lifetime"` // 连接最大存活时长, 单位ms
DisableIdentity bool `json:"disable_identity" yaml:"disable_identity" ini:"disable_identity" toml:"disable_identity"` // Disable set-lib on connect. Default is false.
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
}

26
define/result.go Normal file
View File

@ -0,0 +1,26 @@
// Package define ...
//
// Description : define ...
//
// Author : go_developer@163.com<白茶清欢>
//
// 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 consts.RedisCmd `json:"command"` // 执行的命令
ArgList []string `json:"arg_list"` // 参数列表
Err error `json:"-"` // 失败信息
}

57
go.mod
View File

@ -1,53 +1,34 @@
module git.zhangdeman.cn/zhangdeman/redis
go 1.17
go 1.23.0
toolchain go1.24.2
require (
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20220514080721-7713928d9258
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20230212080829-b9bb99b256ae
git.zhangdeman.cn/zhangdeman/util v0.0.0-20230211164227-256094968151
github.com/gin-gonic/gin v1.8.2
github.com/go-redis/redis/v8 v8.11.5
git.zhangdeman.cn/zhangdeman/consts v0.0.0-20250420101447-0b570213d5c7
git.zhangdeman.cn/zhangdeman/util v0.0.0-20240618042405-6ee2c904644e
git.zhangdeman.cn/zhangdeman/wrapper v0.0.0-20250321102712-1cbfbe959740
github.com/pkg/errors v0.9.1
github.com/stretchr/testify v1.8.1
go.uber.org/zap v1.24.0
gopkg.in/yaml.v2 v2.4.0
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/Jeffail/gabs v1.4.0 // 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.2.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dgrijalva/jwt-go v3.2.0+incompatible // indirect
github.com/cespare/xxhash/v2 v2.3.0 // indirect
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // 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.11.2 // indirect
github.com/go-redis/redis_rate/v9 v9.1.2 // indirect
github.com/goccy/go-json v0.10.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/leodido/go-urn v1.2.1 // 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.17 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/go-redis/redismock/v9 v9.2.0 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mozillazg/go-pinyin v0.20.0 // indirect
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/tidwall/gjson v1.14.4 // 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
github.com/ugorji/go/codec v1.2.9 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.9.0 // indirect
golang.org/x/crypto v0.6.0 // indirect
golang.org/x/net v0.6.0 // indirect
golang.org/x/sys v0.5.0 // indirect
golang.org/x/text v0.7.0 // indirect
google.golang.org/protobuf v1.28.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
go.uber.org/multierr v1.11.0 // indirect
)

364
go.sum
View File

@ -1,311 +1,101 @@
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20220514080721-7713928d9258 h1:HfsZL23OR8TYaeWPpq4zTyzaulBMzE7Sy4Eb44IQde8=
git.zhangdeman.cn/zhangdeman/easymap v0.0.0-20220514080721-7713928d9258/go.mod h1:dB/awTFhiytRxtWC5WQVqDumkvw3ZSAMm3mEGhjcEwc=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20220612104513-3f63f6c673f5 h1:avCnxHO3ubhYwz+DNFE+0OjHUJq+P2R53pKiq8dFLjM=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20220612104513-3f63f6c673f5/go.mod h1:0A5BV9pE31nuFE60TLbP7BIhhV/fcWoi+fHrcV2clJw=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20220626102711-013e3feb3c5b h1:ch0rrtFpFYsgHkTOX1Viwz0nXV5CboYPLGs5pTRoBL4=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20220626102711-013e3feb3c5b/go.mod h1:maPH+eH8+PHplzyJMdXFe1xg1cVq2Ryzo2h/57lwiDs=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20230212080829-b9bb99b256ae h1:W+1px+Eq67KlsvLxVcO6rhCCl1qBeiRcqP0vfajx+nw=
git.zhangdeman.cn/zhangdeman/logger v0.0.0-20230212080829-b9bb99b256ae/go.mod h1:maPH+eH8+PHplzyJMdXFe1xg1cVq2Ryzo2h/57lwiDs=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20220514075609-25936d457a72/go.mod h1:YI/XeTmrr9+8dxa4ThPkmNcEE8WHG5pZkKujpSWwIxM=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20220609072516-022a755fdf2f h1:yAxxukVUdSM5wn264el+QiAEB0OBN/5H7Xw9Z6rLzUY=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20220609072516-022a755fdf2f/go.mod h1:YI/XeTmrr9+8dxa4ThPkmNcEE8WHG5pZkKujpSWwIxM=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20230113095943-b4b3e261e0c4 h1:1WclY9P8l8o/NZ3ZR/mupm8LtowjQ/Q4UNGXR32f0OQ=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20230113095943-b4b3e261e0c4/go.mod h1:zTir/0IWdK3E7n0GiaogyWHADAQnBtTdl2I6Z2/OPqw=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20230211164227-256094968151 h1:j537bRLQL1FlkdXTIaT9Ecjx5eogkPsGiTOWIEFQlc8=
git.zhangdeman.cn/zhangdeman/util v0.0.0-20230211164227-256094968151/go.mod h1:SyRTkOz6gxUVn3S/Qtkf+rhKV0I1ym8lwsT8YjggYFs=
github.com/Jeffail/gabs v1.4.0 h1://5fYRRTq1edjfIrQGvdkcd22pkYUrHZ5YC/H2GJVAo=
github.com/Jeffail/gabs v1.4.0/go.mod h1:6xMvQMK4k33lb7GUUpaAPh6nKMmemQeg5d4gn7/bOXc=
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/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/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=
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/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/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/cespare/xxhash/v2 v2.1.2 h1:YRXhKfTDauu4ajMg1TPgFO5jnlC2HCbmLXMcTG5cbYE=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
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/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
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/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/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
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.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
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.7.7/go.mod h1:axIBovoeJpVj8S3BwE0uPMTeReE4+AfFtqpqaZ1qq1U=
github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8=
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
github.com/gin-gonic/gin v1.8.2 h1:UzKToD9/PoFj/V4rvlKqTRKnQYyz8Sc1MJlv4JHPtvY=
github.com/gin-gonic/gin v1.8.2/go.mod h1:qw5AYuDrzRTnhvusDsrov+fDIxp9Dleuu12h8nfB398=
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.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8=
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
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.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA=
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
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.4.1/go.mod h1:nlOn6nFhuKACm19sB/8EGNn9GlaMV7XkbRSipzJ0Ii4=
github.com/go-playground/validator/v10 v10.10.0 h1:I7mrTYv78z8k8VXa/qJlOlEXn/nBh+BF8dHX5nt/dr0=
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
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/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
github.com/goccy/go-json v0.9.7 h1:IcB+Aqpx/iMHu5Yooh7jEzJk1JZ7Pjtmys2ukPr7EeM=
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA=
github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
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/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
github.com/jonboulle/clockwork v0.3.0 h1:9BSCMi8C+0qdApAp4auwX0RkLGUjs956h0EkuQymUhg=
github.com/jonboulle/clockwork v0.3.0/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
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/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
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.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421 h1:ZqeYNhU3OHLH3mGKHDcjJRFFRrJa6eAM5H+CtDdOsPc=
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 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
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/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
github.com/onsi/ginkgo/v2 v2.0.0/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
github.com/onsi/gomega v1.18.1 h1:M1GfJqGRrBrrGGsbxzV5dqM2U2ApXefZCQpkukxYRLE=
github.com/onsi/gomega v1.18.1/go.mod h1:0q+aL8jAiMXy9hbwj2mr5GziHiwhAIQpFmmtT5hitRs=
github.com/pelletier/go-toml/v2 v2.0.1 h1:8e3L2cCQzLFi2CR4g7vGFuFxX7Jl1kKX8gW+iV0GUKU=
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
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/mozillazg/go-pinyin v0.20.0 h1:BtR3DsxpApHfKReaPO1fCqF4pThRwH9uwvXzm+GnMFQ=
github.com/mozillazg/go-pinyin v0.20.0/go.mod h1:iR4EnMMRXkfpFVV5FMi4FNB6wGq9NV6uDWbUuPhP4Yc=
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/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
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/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.1 h1:5TQK59W5E3v0r2duFAb7P95B6hEeOyEnHRa8MjYSMTY=
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/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
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/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=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go v1.2.7 h1:qYhyWUUd6WbiM+C6JZAUkIJt/1WrjzNHY9+KCIjVqTo=
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/ugorji/go/codec v1.2.8 h1:sgBJS6COt0b/P40VouWKdseidkDgHxYGm0SAglUHfP0=
github.com/ugorji/go/codec v1.2.8/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU=
github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ=
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/multierr v1.9.0 h1:7fIwc/ZtS0q++VgcfqFDxSBZVv/Xo49/SYnDFupUwlI=
go.uber.org/multierr v1.9.0/go.mod h1:X2jQV1h+kxSjClGpnseKVIxpmcjrj7MNnI0bnlfKTVQ=
go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc=
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200520004742-59133d7f0dd7/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781 h1:DzZ89McO9/gWPsQXS/FVKAlG02ZjaQ6AlZRBimEYOd0=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
golang.org/x/net v0.6.0 h1:L4ZwwTvKW9gr0ZMS1yrHD9GZhIuVjOBBnaKH+SPQK0Q=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190904154756-749cb33beabd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
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.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8=
go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E=
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/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/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=
gorm.io/gorm v1.23.5/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk=

View File

@ -1,39 +0,0 @@
// Package redis...
//
// Description : redis...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2021-02-27 5:26 下午
package redis
import (
"git.zhangdeman.cn/zhangdeman/logger"
"go.uber.org/zap/zapcore"
)
// LoggerConfig 日志配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 5:26 下午 2021/2/27
type LoggerConfig struct {
LoggerPath string
LoggerFile string
LoggerLevel zapcore.Level
ConsoleOutput bool
Encoder zapcore.Encoder
SplitConfig *logger.RotateLogConfig
}
// LogFieldConfig 日志字段配置
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 9:20 下午 2021/2/27
type LogFieldConfig struct {
Message string
UsedTimeField string
CommandField string
FlagField string
}

View File

@ -12,10 +12,9 @@ import (
"strings"
"git.zhangdeman.cn/zhangdeman/util"
redisClient "github.com/redis/go-redis/v9"
yml "gopkg.in/yaml.v2"
"github.com/go-redis/redis/v8"
yml "gopkg.in/yaml.v3"
)
// 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
}

144
wrapper.go Normal file
View File

@ -0,0 +1,144 @@
// Package redis ...
//
// Description : redis ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 2024-06-19 16:15
package redis
import (
"context"
"git.zhangdeman.cn/zhangdeman/consts"
"git.zhangdeman.cn/zhangdeman/redis/define"
"strings"
"time"
)
var (
Wrapper = &wrapper{}
)
// wrapper 常用命令的包装
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:16 2024/6/19
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, consts.RedisCommandGet, key)
}
// Del 删除命令
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:19 2024/6/19
func (w *wrapper) Del(ctx context.Context, instanceFlag string, keyList ...string) *define.RedisResult {
return Client.Exec(ctx, instanceFlag, consts.RedisCommandDel, strings.Join(keyList, " "))
}
// SetEx 设置数据并且带有效期, 有效期单位 : s
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:22 2024/6/19
func (w *wrapper) SetEx(ctx context.Context, instanceFlag string, key string, value string, ttl int64, withLock bool) *define.RedisResult {
now := time.Now().Unix()
if ttl > now {
// 传入过期时间大于当前时间, 说明是指定具体时间过期, 做一下处理
ttl = ttl - now
}
if withLock {
return Client.Exec(ctx, instanceFlag, consts.RedisCommandSet, key, value, "EX", ttl, "NX")
}
return Client.Exec(ctx, instanceFlag, consts.RedisCommandSet, key, value, "EX", ttl)
}
// LPop ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:29 2024/6/19
func (w *wrapper) LPop(ctx context.Context, instanceFlag string, key string) *define.RedisResult {
return Client.Exec(ctx, instanceFlag, consts.RedisCommandLpop, key)
}
// RPop ...
//
// Author : go_developer@163.com<白茶清欢>
//
// Date : 16:30 2024/6/19
func (w *wrapper) RPop(ctx context.Context, instanceFlag string, key string) *define.RedisResult {
return Client.Exec(ctx, instanceFlag, consts.RedisCommandRpop, key)
}
// LPush ...
//
// Author : go_developer@163.com<白茶清欢>
//
// 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, consts.RedisCommandLpush, key, value)
}
// RPush ...
//
// Author : go_developer@163.com<白茶清欢>
//
// 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, consts.RedisCommandRpush, key, value)
}
// HGet ...
//
// Author : go_developer@163.com<白茶清欢>
//
// 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, consts.RedisCommandHget, key, field)
}
// HSet ...
//
// Author : go_developer@163.com<白茶清欢>
//
// 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, consts.RedisCommandHset, key, field, value)
}
// HDel ...
//
// Author : go_developer@163.com<白茶清欢>
//
// 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, consts.RedisCommandHdel, key, strings.Join(fieldList, " "))
}