Interleaving Watch Multi / exec在单个Redis连接上。预期或奇怪的行为?

时间:2014-10-28 11:38:50

标签: concurrency redis

考虑一个前置应用程序,其中每个请求共享相同的Redis连接,我认为这是推荐的方式(?)。

在这种情况下,我相信我会看到一些奇怪的watch multi/exec行为。具体来说,我希望两个交易中的一个因为乐观锁定失败而失败(即:watch后卫),但两者似乎都没有发脾气,但导致错误的最终值。

为了说明看下面的设计方案。它在Node中,但我相信这是一般性的。这会并行运行2个进程,这两个进程都会更新计数器。 (它基本上实现了Watch的典型示例,如Redis Docs中所示。

预期结果是第一个进程导致增量为1而第二个进程无法更新并返回null。相反,结果是两个进程都用1更新计数器。但是一个基于一个陈旧的计数器,所以最后计数器增加1而不是2。

    //NOTE: db is a promisified version of node-redis, but that really doesn't matter
    var db = Source.app.repos.redis._raw;
    Promise.all(_.reduce([1, 2], function(arr, val) {
        db.watch("incr");
        var p = Promise.resolve()
            .then(function() {
                return db.get("incr");
            })
            .then(function(val) { //say 'val' returns '4' for both processes.
                console.log(val);
                val++;
                db.multi();
                db.set("incr", val);
                return db.exec();
            })
            .then(function(resultShouldBeNullAtLeastOnce) {
                console.log(resultShouldBeNullAtLeastOnce);
                return; //explict end
            });
        arr.push(p);
        return arr;
    }, [])).then(function() {
        console.log("done all");
        next(undefined);
    })

在拖尾Redis'MONITOR命令时会看到结果交错:

    1414491001.635833 [0 127.0.0.1:60979] "watch" "incr"
    1414491001.635936 [0 127.0.0.1:60979] "watch" "incr"
    1414491001.636225 [0 127.0.0.1:60979] "get" "incr"
    1414491001.636242 [0 127.0.0.1:60979] "get" "incr"
    1414491001.636533 [0 127.0.0.1:60979] "multi"
    1414491001.636723 [0 127.0.0.1:60979] "set" "incr" "5"
    1414491001.636737 [0 127.0.0.1:60979] "exec"
    1414491001.639660 [0 127.0.0.1:60979] "multi"
    1414491001.639691 [0 127.0.0.1:60979] "set" "incr" "5"
    1414491001.639704 [0 127.0.0.1:60979] "exec"

这是预期的行为吗?使用多个redis连接会绕过这个问题吗?

1 个答案:

答案 0 :(得分:0)

回答我自己的问题:

这是预期的行为。第一个exec取消了所有属性。因此,第二个multi/exec没有守卫。

它位于docs,但它相当隐蔽。

解决方案:使用多个连接,尽管SO上有一些答案明确地警告这个,因为它(引用)不应该被需要'。在这种情况下,需要IT。