代码之家  ›  专栏  ›  技术社区  ›  Rick

Redis不会在事务中返回WRONGTYPE作为错误

  •  0
  • Rick  · 技术社区  · 4 年前

    如果已经问过这个问题,请道歉。首先,让我演示一下如何重现我的问题:

    1. 在docker容器中运行Redis
    2. 连接Redis并执行以下命令:
    > SET test 10
    
    1. 在Go中,运行以下代码:
    func main() {
        redisClient := getConnection() // Abstracting get connection for simplicity
    
        r, err := redisClient.Do("HSET", "test", "f1", "v1", "f2", "v2")
        fmt.Printf("%+v e: %+v\n")
    }
    

    很公平,在这一步中显示了以下错误(这意味着 err != nil ):

    WRONGTYPE Operation against a key holding the wrong kind of value e: WRONGTYPE Operation against a key holding the wrong kind of value
    
    1. 相比之下,执行以下代码:
    func main() {
        redisClient := getConnection()
    
        redisClient.Send("MULTI")
    
        redisClient.Send("HSET", "test", "f1", "v1", "f2", "v2")
    
        r, err := redisClient.Do("EXEC")
        fmt.Printf("%+v e: %+v\n")
    }
    

    正在打印的行是:

    WRONGTYPE Operation against a key holding the wrong kind of value e: <nil>
    

    正如我所料,这对我来说似乎不一致 MULTI 返回 WRONGTYPE 误差变量也是如此。

    这是故意的行为还是我错过了什么?

    0 回复  |  直到 4 年前
        1
  •  0
  •   Cerise Limón    4 年前

    Redis事务中的每个命令都有两个结果。一个是将命令添加到事务中的结果,另一个是在事务中执行命令的结果。

    这个 Do 方法返回将命令添加到事务的结果。

    Redis EXEC 命令返回一个数组,其中每个元素都是事务中执行命令的结果。检查每个元素以检查单个命令错误:

    values, err := redis.Values(redisClient.Do("EXEC"))
    if err != nil {
        // Handle error
    }
    if err, ok := values[0].(redis.Error); ok {
        // Handle error for command 0.
        // Adjust the index to match the actual index of 
        // of the HMSET command in the transaction.
    }
    

    用于测试事务命令错误的辅助函数可能很有用:

    func execValues(reply interface{}, err error) ([]interface{}, error) {
        if err != nil {
            return nil, err
        }
        values, ok := reply.([]interface{})
        if !ok {
            return nil, fmt.Errorf("unexpected type for EXEC reply, got type %T", reply)
        }
        for _, v := range values {
            if err, ok := v.(redis.Error); ok {
                return values, err
            }
        }
        return values, nil
    }
    

    这样使用它:

    values, err := execValues(redisClient.Do("EXEC"))
    if err != nil {
        // Handle error.
    }