2012-08-06 28 views
1

我正在用户注册时使用同一个web服务的电子邮件地址进行负载测试,同时连接的前10个用户将始终注册。redis和watch + multi允许并发用户

我正在使用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 [email protected] 
2 email is locked [email protected] 
3 email is locked [email protected] 
4 email is locked [email protected] 
5 email is locked [email protected] 
6 email is locked [email protected] 
7 email is locked [email protected] 
8 email is locked [email protected] 
9 email is locked [email protected] 
10 email is locked [email protected] 

难道我做错了什么或Redis的无法处理这么大的并发性。 另外这是普通的定义:

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

回答

1

是的!经过一夜的休息,当然解决方案来到我的淋浴。

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

+6

yay阵雨 – Roest 2012-08-07 17:06:37

0

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

+0

我也用过这种方法。单身连接上99%的操作。但对于需要监视的少数操作员,我创建了一个新实例。 – Auras 2016-02-09 14:29:58