升级redis client实现
This commit is contained in:
		@ -8,6 +8,8 @@
 | 
				
			|||||||
package abstract
 | 
					package abstract
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"git.zhangdeman.cn/zhangdeman/redis/define"
 | 
				
			||||||
	"github.com/redis/go-redis/v9"
 | 
						"github.com/redis/go-redis/v9"
 | 
				
			||||||
	"go.uber.org/zap"
 | 
						"go.uber.org/zap"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@ -18,9 +20,11 @@ import (
 | 
				
			|||||||
//
 | 
					//
 | 
				
			||||||
// Date : 15:09 2024/6/18
 | 
					// Date : 15:09 2024/6/18
 | 
				
			||||||
type IRedisClient interface {
 | 
					type IRedisClient interface {
 | 
				
			||||||
	GetRealClient(instanceFlag string) *redis.ClusterClient                    // 获取客户端连接
 | 
						GetRealClient(instanceFlag string) *redis.ClusterClient                                         // 获取客户端连接
 | 
				
			||||||
	GetRealClientWithError(instanceFlag string) (*redis.ClusterClient, error)  // 获取带error的客户端连接
 | 
						GetRealClientWithError(instanceFlag string) (*redis.ClusterClient, error)                       // 获取带error的客户端连接
 | 
				
			||||||
	AddClient(instanceFlag string, instanceConfig *redis.ClusterOptions) error // 添加新的客户端连接
 | 
						AddClient(instanceFlag string, instanceConfig *redis.ClusterOptions) error                      // 添加新的客户端连接
 | 
				
			||||||
	RemoveClient(instanceFlag string)                                          // 移除一个客户端连接
 | 
						RemoveClient(instanceFlag string)                                                               // 移除一个客户端连接
 | 
				
			||||||
	SetLogger(loggerInstance *zap.Logger)                                      // 设置日志实例
 | 
						SetLogger(loggerInstance *zap.Logger)                                                           // 设置日志实例, 全局生效, 而非针对某一个实例
 | 
				
			||||||
 | 
						Exec(ctx context.Context, instanceFlag string, command string, args ...any) *define.RedisResult // 执行任意命令
 | 
				
			||||||
 | 
						SetCommandWhiteList(command []string)                                                           // 设置命令的白名单,全局生效, 而非单独针对某一个实例
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										104
									
								
								client.go
									
									
									
									
									
								
							
							
						
						
									
										104
									
								
								client.go
									
									
									
									
									
								
							@ -8,26 +8,120 @@
 | 
				
			|||||||
package redis
 | 
					package redis
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
	"git.zhangdeman.cn/zhangdeman/redis/abstract"
 | 
						"git.zhangdeman.cn/zhangdeman/redis/abstract"
 | 
				
			||||||
 | 
						"git.zhangdeman.cn/zhangdeman/redis/define"
 | 
				
			||||||
 | 
						"git.zhangdeman.cn/zhangdeman/wrapper"
 | 
				
			||||||
	"github.com/pkg/errors"
 | 
						"github.com/pkg/errors"
 | 
				
			||||||
	redisClient "github.com/redis/go-redis/v9"
 | 
						redisClient "github.com/redis/go-redis/v9"
 | 
				
			||||||
	"go.uber.org/zap"
 | 
						"go.uber.org/zap"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
	"sync"
 | 
						"sync"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var Client abstract.IRedisClient
 | 
					var Client abstract.IRedisClient
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func init() {
 | 
					func init() {
 | 
				
			||||||
	Client = &OwnClient{
 | 
						Client = &OwnClient{
 | 
				
			||||||
		lock:          &sync.RWMutex{},
 | 
							lock:              &sync.RWMutex{},
 | 
				
			||||||
		instanceTable: make(map[string]*redisClient.ClusterClient),
 | 
							instanceTable:     make(map[string]*redisClient.ClusterClient),
 | 
				
			||||||
 | 
							whiteCommandTable: make(map[string]bool),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type OwnClient struct {
 | 
					type OwnClient struct {
 | 
				
			||||||
	lock          *sync.RWMutex
 | 
						lock              *sync.RWMutex
 | 
				
			||||||
	instanceTable map[string]*redisClient.ClusterClient
 | 
						instanceTable     map[string]*redisClient.ClusterClient
 | 
				
			||||||
	logger        *zap.Logger
 | 
						whiteCommandTable map[string]bool
 | 
				
			||||||
 | 
						logger            *zap.Logger
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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 : 11:05 2024/6/19
 | 
				
			||||||
 | 
					func (o *OwnClient) Exec(ctx context.Context, instanceFlag string, command string, args ...any) *define.RedisResult {
 | 
				
			||||||
 | 
						var (
 | 
				
			||||||
 | 
							instance *redisClient.ClusterClient
 | 
				
			||||||
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						cmdParamList := []any{
 | 
				
			||||||
 | 
							command,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						argStrList := make([]string, 0)
 | 
				
			||||||
 | 
						for _, itemArg := range args {
 | 
				
			||||||
 | 
							argStrList = append(argStrList, wrapper.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,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							res.FinishTime = time.Now().UnixMilli()
 | 
				
			||||||
 | 
							res.UsedTime = res.FinishTime - res.StartTime
 | 
				
			||||||
 | 
							if nil == o.logger {
 | 
				
			||||||
 | 
								// 未注入日志实例
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							o.logger.Info(
 | 
				
			||||||
 | 
								"Redis命令执行记录",
 | 
				
			||||||
 | 
								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("arg_list", strings.Join(res.ArgList, " ")),
 | 
				
			||||||
 | 
								zap.String("execute_result", res.Result),
 | 
				
			||||||
 | 
								zap.Error(res.Err),
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
						if instance, res.Err = o.GetRealClientWithError(instanceFlag); nil != res.Err {
 | 
				
			||||||
 | 
							return res
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if nil == ctx {
 | 
				
			||||||
 | 
							ctx = context.Background()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						cmdRes := instance.Do(ctx, cmdParamList...)
 | 
				
			||||||
 | 
						if res.Err = cmdRes.Err(); nil != res.Err {
 | 
				
			||||||
 | 
							return res
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						res.Result = cmdRes.String()
 | 
				
			||||||
 | 
						return res
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// SetCommandWhiteList 设置命令白名单, 空 或者 包含 * 则认为所有命令均允许执行
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Author : go_developer@163.com<白茶清欢>
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Date : 11:02 2024/6/19
 | 
				
			||||||
 | 
					func (o *OwnClient) SetCommandWhiteList(commandList []string) {
 | 
				
			||||||
 | 
						o.lock.Lock()
 | 
				
			||||||
 | 
						defer o.lock.Unlock()
 | 
				
			||||||
 | 
						for _, itemCommand := range commandList {
 | 
				
			||||||
 | 
							o.whiteCommandTable[strings.ToLower(strings.TrimSpace(itemCommand))] = true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (o *OwnClient) GetRealClient(instanceFlag string) *redisClient.ClusterClient {
 | 
					func (o *OwnClient) GetRealClient(instanceFlag string) *redisClient.ClusterClient {
 | 
				
			||||||
 | 
				
			|||||||
							
								
								
									
										24
									
								
								define/result.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								define/result.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,24 @@
 | 
				
			|||||||
 | 
					// Package define ...
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Description : define ...
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Author : go_developer@163.com<白茶清欢>
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Date : 2024-06-19 10:49
 | 
				
			||||||
 | 
					package define
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// 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:"-"`             // 失败信息
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Reference in New Issue
	
	Block a user