package dbclient import ( "context" "fmt" "log" "github.com/redis/go-redis/v9" ) // RedisPipeline Redis Pipeline 操作 type RedisPipeline struct { client *RedisClient commands []RedisCommand ctx context.Context } // RedisCommand Redis 命令结构 type RedisCommand struct { Command string Args []interface{} Result interface{} Error error } // NewRedisPipeline 创建新的 Redis Pipeline func (r *RedisClient) NewPipeline(ctx context.Context) *RedisPipeline { return &RedisPipeline{ client: r, commands: make([]RedisCommand, 0), ctx: ctx, } } // AddCommand 添加命令到 Pipeline func (p *RedisPipeline) AddCommand(command string, args ...interface{}) { p.commands = append(p.commands, RedisCommand{ Command: command, Args: args, }) } // Execute 使用 go-redis 原生 Pipeline 执行所有命令 func (p *RedisPipeline) Execute() ([]interface{}, error) { if len(p.commands) == 0 { return nil, nil } pipe := p.client.client.Pipeline() cmds := make([]*redis.Cmd, len(p.commands)) for i, c := range p.commands { cmds[i] = pipe.Do(p.ctx, append([]interface{}{c.Command}, c.Args...)...) } // 一次性发送所有命令 results := make([]interface{}, len(p.commands)) cmdResults, err := pipe.Exec(p.ctx) if err != nil && err != redis.Nil { log.Printf("[RedisPipeline] Exec 错误: %v", err) } for i, cmd := range cmds { result, cmdErr := cmd.Result() results[i] = result p.commands[i].Result = result p.commands[i].Error = cmdErr } // 如果 Exec 返回了命令结果(部分 Redis 版本),使用它们 for i, cr := range cmdResults { if cr.Err() != nil && cr.Err() != redis.Nil { p.commands[i].Error = cr.Err() if i < len(results) { results[i] = nil } } } _ = results // 已经通过 cmds 获取 return results, nil } // GetCommands 获取 Pipeline 中的命令列表 func (p *RedisPipeline) GetCommands() []RedisCommand { return p.commands } // Len 获取 Pipeline 中的命令数量 func (p *RedisPipeline) Len() int { return len(p.commands) } // Clear 清空 Pipeline func (p *RedisPipeline) Clear() { p.commands = make([]RedisCommand, 0) } // RedisTransaction Redis 事务支持 type RedisTransaction struct { client *RedisClient watch []string cmds []RedisCommand ctx context.Context } // NewRedisTransaction 创建新的 Redis 事务 func (r *RedisClient) NewTransaction(ctx context.Context, watch ...string) *RedisTransaction { return &RedisTransaction{ client: r, watch: watch, ctx: ctx, } } // AddCommand 添加命令到事务 func (tx *RedisTransaction) AddCommand(command string, args ...interface{}) { tx.cmds = append(tx.cmds, RedisCommand{ Command: command, Args: args, }) } // Exec 使用 go-redis Watch + TxPipeline 执行事务(MULTI/EXEC) func (tx *RedisTransaction) Exec() ([]interface{}, error) { pipe := tx.client.client.TxPipeline() // 添加所有命令 cmds := make([]*redis.Cmd, len(tx.cmds)) for i, c := range tx.cmds { cmds[i] = pipe.Do(tx.ctx, append([]interface{}{c.Command}, c.Args...)...) } // TxPipeline 自动发送 MULTI/EXEC results := make([]interface{}, len(tx.cmds)) _, err := pipe.Exec(tx.ctx) for i, cmd := range cmds { result, cmdErr := cmd.Result() results[i] = result tx.cmds[i].Result = result tx.cmds[i].Error = cmdErr } if err != nil && err != redis.Nil { return results, fmt.Errorf("事务执行失败: %v", err) } return results, nil }