首页 > 解决方案 > 使用 go-redis/redis 在 Golang 中进行 Multi WATCH

问题描述

我正在尝试使用https://github.com/go-redis/redis在一个事务中执行这 4 个 redis 调用:

func getHost(key) host, score, error{
numberOfHosts, err := rdb.ZCard(key).Result()
if err != nil {
return nil, 0, err
}

host, err := rdb.ZRangeByScoreWithScores(key, redis.ZRangeBy{
    Min:    "0",
    Max:    strconv.Itoa(maxScore),
    Offset: numberOfHosts - 1,
    Count:  1,
}).Result()
if err != nil {
    return nil, 0, err
}

score := host[0].Score
member, err := json.Marshal(host[0].Member)
if err != nil {
    return nil, 0, err
}

if int(score) < maxCapacity {
    rdb.ZIncrBy(key, score+1, string(member))
}

host, err := rdb.GetHost(string(member))
if err != nil {
    return nil, 0, err
}
return host, int(score), nil
}

我在文档中找到了这个https://godoc.org/github.com/go-redis/redis#Client.Watch,我正在尝试用它做点什么,但目前有点困难。

有人已经这样做并且可以提供建议吗?

编辑:我试图这样做:

count := func(key string) error {
        txf := func(tx *redis.Tx) error {
            numberOfHosts, err := tx.ZCard(key).Result()
            if err != nil {
                return err
            }
            numberOfHosts--
            _, err = tx.Pipelined(func(pipe redis.Pipeliner) error {
                getHostKey := func(key string, numberOfHosts int) error {
                    txf := func(tx *redis.Tx) error {
                        host, err := tx.ZRangeByScoreWithScores(key, redis.ZRangeBy{
                            Min:    "0",
                            Max:    strconv.Itoa(maxCapacity),
                            Offset: numberOfHosts,
                            Count:  1,
                        }).Result()
                        if err != nil {
                            return err
                        }
                        if len(host) == 0 {
                            return fmt.Errorf("Get Host did not return a host for the key: %v", key)
                        }
                        score := host[0].Score
                        member, err := json.Marshal(host[0].Member)
                        if err != nil {
                            return err
                        }
                        score++
                        _, err = tx.Pipelined(func(pipe redis.Pipeliner) error {
                            if int(score) < maxCapacity {
                                incScore := func(key string, score int, member string) (*Host, int, error) {
                                    txf := func(tx *redis.Tx) error {
                                        tx.ZIncrBy(key, score, string(member))
                                            host, err := rc.GetHost(string(member))
                                            if err != nil {
                                                return nil, 0, err
                                            }
                                            return host, int(score), nil
                                        }
                                    }
                                    err := rc.Client.Watch(txf, key)
                                    if err != redis.TxFailedErr {
                                        return err
                                    }
                                }
                            }
                        })
                    }
                    err := rc.Client.Watch(txf, key)
                    if err != redis.TxFailedErr {
                        return err
                    }
                }
                if err := getHostKey(key, numberOfHosts); err != nil {
                    return err
                }
            })
        }
        err := rc.Client.Watch(txf, key)
        if err != redis.TxFailedErr {
            return err
        }
    }

    if err := count(key); err != nil {
        return nil, 0, err

但是编译器对来自前一个手表的所有变量并不满意。

我将研究 LUA 脚本

标签: goredis

解决方案


推荐阅读