【问题标题】:redis and watch + multi allows concurrent usersredis 和 watch + multi 允许并发用户
【发布时间】:2012-08-06 16:57:24
【问题描述】:

我正在对使用相同电子邮件地址的 Web 服务注册用户进行负载测试,同时连接的前 10 个用户将始终注册。

我正在使用 WATCH 和 MULTI,但这似乎不起作用。

我正在调用 save() 来保存用户。

this.insert = function(callback) {
    this.preInsert();

    created = new Date();
    updated = new Date();

    // Also with these uncommented it still doesn't work
    // Common.client.watch("u:" + this.username);
    // Common.client.watch("em:" + this.email);

    console.log(ID + " email is locked " + this.email);
    Common.client.multi()
    .set("u:" + this.username, ID)
    .hmset("u:" + ID, 
        {"username": this.username
        ,"password": this.password
        ,"email": this.email
        ,"payment_plan": payment_plan
        ,"created": created.getTime()
        ,"updated": updated.getTime()
        ,"avatar": this.avatar})
    .zadd("u:users", 0, ID)
    .sadd("u:emails", this.email)
    .set("u:"+ ID + ":stats", 0)
    .set("em:" + this.email, ID)
    .exec();

    this.postInsert();

    if (callback != null)
        callback(null, this);
}

this.save = function(callback) {
    // new user
    if (ID == -1) {
        var u = this;

        Common.client.watch("u:" + this.username);
        Common.client.exists("u:" + this.username, function(error, exists) {
            // This username already exists
            if (exists == 1) {
                Common.client.unwatch();
                if (callback != null)
                    callback({code: 100, message: "This username already exists"});
            }
            else {
                Common.client.watch("em:" + u.email);
                Common.client.get("em:" + u.email, function(err, emailExists) {
                    if (emailExists != null) {
                        Common.client.unwatch();
                        if (callback != null)
                            callback({code: 101, message: "This email is already in use"});
                    }
                    else {
                        Common.client.incr("u:nextID", function(error, id) {
                            if (error) callback(error);
                            else {
                                ID = id;
                                u.insert(callback);
                            } 
                        });
                    }
                });
            }
        });
    }
    // existing user
    else {
        var u = this;
        Common.client.get("em:" + this.email, function(err, emailExists) {
            if (emailExists != ID && emailExists) {
                if (callback != null) {
                    callback({code: 101, message: "This email is already in use " + ID + " " + emailExists});
                }
            }
            else {
                u.update(callback);
            }
        });
    }
}

输出几乎总是:

1 email is locked test@test.com
2 email is locked test@test.com
3 email is locked test@test.com
4 email is locked test@test.com
5 email is locked test@test.com
6 email is locked test@test.com
7 email is locked test@test.com
8 email is locked test@test.com
9 email is locked test@test.com
10 email is locked test@test.com

是我做错了什么还是 redis 无法处理那么多并发。 这也是Common的定义:

var Common = {
    client: redis.createClient(),
...
};

【问题讨论】:

    标签: node.js transactions load redis


    【解决方案1】:

    是的!经过一晚的休息,我在洗澡时当然找到了解决方案。

    问题是我为整个应用程序使用了一个 redis 线程,并且所有连接都在该线程上注册了手表。当然,它并不表示密钥已被其他客户端修改,因为没有其他客户端。

    【讨论】:

      【解决方案2】:

      我知道这个帖子有 8 个月的历史,但无论如何,我的想法仍然可以帮助某人。有一个问题我仍然无法理解,我什至开始了自己的主题Redis WATCH MULTI EXEC by one client,我参考了你的。我现在使用“每个事务的连接”方法,这意味着如果我需要使用 WATCH-MULTI-EXEC 进行事务,我会创建新的连接。在其他原子操作的情况下,我使用连接,它是在应用程序启动期间创建的。不确定此方法是否有效,因为创建新连接意味着创建 + 授权,这会产生延迟,但它有效。

      【讨论】:

      • 我也用过这个方法。单例连接上 99% 的操作。但是对于需要监视的少数操作,我创建了一个新实例。
      猜你喜欢
      • 2019-11-17
      • 2013-03-24
      • 1970-01-01
      • 2021-12-11
      • 1970-01-01
      • 2011-06-25
      • 1970-01-01
      • 1970-01-01
      • 2021-06-29
      相关资源
      最近更新 更多