1

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(),
...
};
4

2 に答える 2

1

はい!もちろん一晩の休息の後、解決策はシャワーで私に来ました。

問題は、アプリ全体に単一のredisスレッドを使用し、すべての接続がそのスレッドに時計を登録したことでした。もちろん、他のクライアントがなかったため、キーが別のクライアントによって変更されたことを示すものではありませんでした。

于 2012-08-07T07:46:45.807 に答える
0

このスレッドは8か月前のものですが、とにかく、私の考えはまだ誰かを助けることができます。まだ理解できない問題があります。この問題専用の独自のスレッドを1つのクライアントでRedisWATCHMULTI EXECを開始しました。ここで、あなたのスレッドを参照します。現在、「トランザクションごとの接続」方式を使用しています。これは、WATCH-MULTI-EXECでトランザクションを実行する必要がある場合に、新しい接続を作成することを意味します。その他の場合、アトミック操作では、アプリの起動時に作成される接続を使用します。新しい接続を作成することは作成と承認を意味し、これにより遅延が発生するため、この方法が効果的かどうかはわかりませんが、機能します。

于 2013-04-03T18:11:51.643 に答える