gomodule / redigo

Go client for Redis
Apache License 2.0
9.76k stars 1.25k forks source link

use pipline send got ERR wrong number of arguments for 'set' command #637

Closed Victoryship closed 1 year ago

Victoryship commented 1 year ago
client, err := redisclient.GetRedisPoolWithCtx(ctx, "mfRedis")
if err != nil {
    log.Error(" get redis client error: ", zap.Error(err))
    return
}
defer client.Close()

client.Send("set", "name", 1)
client.Flush()

fmt.Println(client.ReceiveWithCtx(ctx))

get result

企业微信截图_16715013406534

init pool

redisclient.InitRedisPoolByDefault([]string{"redis", "mfRedis"})

func InitRedisPoolByDefault(redisNames []string) {
    InitRedisPool(redisNames, 100, 50, 1800)
}

func InitRedisPool(redisNames []string, poolSize int, maxActive int, timeOut int) {
    if len(redisNames) == 0 {
        return
    }

    for _, redisName := range redisNames {
        pool[redisName] = &RedisPool{}
        pool[redisName].Do(func() {
            redisHost := tools.GetConfig(redisName + ".host")
            port := tools.GetConfig(redisName + ".port")
            pool[redisName].pool = &redis.Pool{
                MaxIdle:     poolSize,
                MaxActive:   maxActive,
                IdleTimeout: time.Duration(timeOut) * time.Second,
                Wait:        true,
                // Dial or DialContext must be set. When both are set, DialContext takes precedence over Dial.
                Dial: func() (redis.Conn, error) { return redis.Dial("tcp", redisHost+":"+port) },
            }
            ser := false
            if tools.GetConfig(redisName+".serialize") == "true" {
                ser = true
            }
            prefix := tools.GetConfig(redisName + ".prefix")
            pool[redisName].serialize = ser
            pool[redisName].prefix = prefix
        })
    }

}

func GetRedisPoolWithCtx(ctx context.Context, redisName string) (*RedisClient, error) {
    redisPool, ok := pool[redisName]
    if !ok {
        return nil, errors.New("redis pool not init")
    }

    pol, err := redisPool.pool.GetContext(ctx)
    if err != nil {
        return nil, err
    }

    return &RedisClient{client: pol, prefix: redisPool.prefix, isSerialize: redisPool.serialize}, nil
}

redis version 企业微信截图_16715016662386

go version 1.17 redigo version 1.8.9

Victoryship commented 1 year ago

But I don't need send to be normal。

res, err1 := redis.String(client.DoCommandWithCtx(ctx, "set", "name", 1))
fmt.Println(res, err1)

//client.Send("set", "name", 1)
//client.Flush()

//fmt.Println(client.ReceiveWithCtx(ctx))

println OK 企业微信截图_16715027943529

How to use the pipline with send ??? Thanks !

FZambia commented 1 year ago

@Victoryship hello, could you please post the complete snippet which reproduces this to run locally? I successfully used pipelining with redigo – so definitely there is a way to achieve it.

Victoryship commented 1 year ago

init redis pool。 redisclient.InitRedisPoolByDefault([]string{"redis", "mfRedis"})

redis config like this [redis] host=127.0.0.1 port=6379 prefix=im_ serialize=true db=0

then get redis conn from pool with name

client, err := redisclient.GetRedisPoolWithCtx(ctx, "mfRedis")
  if err != nil {
      log.Error(" get redis client error: ", zap.Error(err))
      return
  }
  defer client.Close()

  client.Send("set", "name", 1)
  client.Flush()

  fmt.Println(client.ReceiveWithCtx(ctx))

got ERR wrong number of arguments for 'set' command

Victoryship commented 1 year ago

and my redis pool package is

       package redisclient

       import (
      "context"
      "errors"
      "sync"
      "time"

      "go_friends/pkg/serialize"
      "go_friends/tools"

      "github.com/gomodule/redigo/redis"
      log "github.com/sirupsen/logrus"
      "go.uber.org/zap"
  )

  type RedisClient struct {
      client      redis.Conn
      prefix      string
      isSerialize bool
  }

  //var redisMap = make(map[string]*RedisClient)

  func GetRedisClient(redisName string) *RedisClient {
      redisHost := tools.GetConfig(redisName + ".host")
      port := tools.GetConfig(redisName + ".port")
      db := tools.GetConfigInt(redisName + ".db")
      //opt := redis.DialOption{}
      client1, err := redis.Dial("tcp", redisHost+":"+port)
      redis.DialDatabase(db)
      if err != nil {
          panic("fuck the error")
      }
      //redis.Pool{}
      ser := false
      if tools.GetConfig(redisName+".serialize") == "true" {
          ser = true
      }
      prefix := tools.GetConfig(redisName + ".prefix")
      return &RedisClient{client: client1, prefix: prefix, isSerialize: ser}
  }

  func (redisClient *RedisClient) Close() {
      if err := redisClient.client.Close(); err != nil {
          log.Error(" close redis conn error: ", zap.Error(err))
      }
  }

  type RedisPool struct {
      pool      *redis.Pool
      serialize bool
      prefix    string
      sync.Once
  }

  var pool = make(map[string]*RedisPool)

  func InitRedisPool(redisNames []string, poolSize int, maxActive int, timeOut int) {
      if len(redisNames) == 0 {
          return
      }

      for _, redisName := range redisNames {
          pool[redisName] = &RedisPool{}
          pool[redisName].Do(func() {
              redisHost := tools.GetConfig(redisName + ".host")
              port := tools.GetConfig(redisName + ".port")
              pool[redisName].pool = &redis.Pool{
                  MaxIdle:     poolSize,
                  MaxActive:   maxActive,
                  IdleTimeout: time.Duration(timeOut) * time.Second,
                  Wait:        true,
                  // Dial or DialContext must be set. When both are set, DialContext takes precedence over Dial.
                  Dial: func() (redis.Conn, error) { return redis.Dial("tcp", redisHost+":"+port) },
              }
              ser := false
              if tools.GetConfig(redisName+".serialize") == "true" {
                  ser = true
              }
              prefix := tools.GetConfig(redisName + ".prefix")
              pool[redisName].serialize = ser
              pool[redisName].prefix = prefix
          })
      }

  }
  func InitRedisPoolWithTimeOut(redisNames []string, poolSize int, maxActive int, timeout int) {
      InitRedisPool(redisNames, poolSize, maxActive, timeout)
  }

  func InitRedisPoolByDefault(redisNames []string) {
      InitRedisPool(redisNames, 100, 50, 1800)
  }
  func ClosePool(redisName string) {
      redisPool, ok := pool[redisName]
      if ok {
          redisPool.pool.Close()
      }
  }
  func GetRedisWithPool(redisName string) (*RedisClient, error) {
      redisPool, ok := pool[redisName]
      if !ok {
          return nil, errors.New("redis pool not init")
      }
      return &RedisClient{client: redisPool.pool.Get(), prefix: redisPool.prefix, isSerialize: redisPool.serialize}, nil
  }

  func GetRedisPoolWithCtx(ctx context.Context, redisName string) (*RedisClient, error) {
      redisPool, ok := pool[redisName]
      if !ok {
          return nil, errors.New("redis pool not init")
      }

      pol, err := redisPool.pool.GetContext(ctx)
      if err != nil {
          return nil, err
      }

      return &RedisClient{client: pol, prefix: redisPool.prefix, isSerialize: redisPool.serialize}, nil
  }

  func (redisClient *RedisClient) Do(commandName string, args ...interface{}) (reply interface{}) {
      res, err := redisClient.client.Do(commandName, args...)
      if err != nil {
          log.Error("do redis err")
          log.Error(err)
      }
      return res
  }

  func (redisClient *RedisClient) DoCommandWithCtx(ctx context.Context, command string, args ...interface{}) (interface{}, error) {
      return redis.DoContext(redisClient.client, ctx, command, args...)
  }

  func (redisClient *RedisClient) DoCommandWithTimeout(duration time.Duration, command string, args ...interface{}) (interface{}, error) {
      return redis.DoWithTimeout(redisClient.client, duration, command, args...)
  }

  func (redisClient *RedisClient) Send(commandName string, args ...interface{}) error {
      return redisClient.client.Send(commandName, args)
  }

  func (redisClient *RedisClient) Flush() error {
      return redisClient.client.Flush()
  }

  func (redisClient *RedisClient) ReceiveWithCtx(ctx context.Context) (reply interface{}, err error) {
      return redis.ReceiveContext(redisClient.client, ctx)
  }

  func (redisClient *RedisClient) GetKey(key string) string {
      if redisClient.prefix != "" {
          key = redisClient.prefix + key
      }
      return key
  }

  func (redisClient *RedisClient) GetSerializeValue(value interface{}) interface{} {
      encoder := serialize.NewSerializer()
      var err error
      value, err = encoder.Encode(value)
      if err != nil {
          log.Error("serialize error")
          return value
      }
      return value
  }

  func (redisClient *RedisClient) GetUnSerializeValue(value interface{}) interface{} {
      switch value.(type) {
      case string:
          return decode(value.(string))
      case map[string]interface{}:
          m1 := value.(map[string]interface{})
          for key, v := range m1 {
              m1[key] = decode(v.(string))
          }
          return m1

      case map[string]string:
          m1 := value.(map[string]string)
          m2 := make(map[string]interface{})
          for key, v := range m1 {
              m2[key] = decode(v)
          }
          return m2
      case []string:
          m1 := value.([]string)
          var m2 []interface{}
          for _, v := range m1 {
              m2 = append(m2, decode(v))
          }
          return m2
      }
      return value
  }

  func decode(value string) interface{} {
      decoder := serialize.NewUnSerializer(value)
      if val1, err := decoder.Decode(); err != nil {
          log.Error("unserialize error")
          return value
      } else {
          return val1
      }
  }
FZambia commented 1 year ago

This func from your code:

  func (redisClient *RedisClient) Send(commandName string, args ...interface{}) error {
      return redisClient.client.Send(commandName, args)
  }

Must be:

  func (redisClient *RedisClient) Send(commandName string, args ...interface{}) error {
      return redisClient.client.Send(commandName, args...)
  }
Victoryship commented 1 year ago

thanks very much. I'm careless