2012-08-06 64 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