Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/redis/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Concurrency 在单个Redis连接上交错观看Multi/exec。预期的还是奇怪的行为?_Concurrency_Redis - Fatal编程技术网

Concurrency 在单个Redis连接上交错观看Multi/exec。预期的还是奇怪的行为?

Concurrency 在单个Redis连接上交错观看Multi/exec。预期的还是奇怪的行为?,concurrency,redis,Concurrency,Redis,考虑一个正面应用程序,其中每个请求共享相同的Redis连接,我认为这是推荐的方式(?) 在这种情况下,我相信我看到了一些奇怪的观察multi/exec行为。具体地说,我预计两个事务中的一个会因为乐观锁定失败而失败(即,watchguard),但这两个事务似乎都没有发脾气,但会导致错误的最终值 为了说明,请参见下面的人为场景。它在节点中,但我相信这是一般的事情。这将并行运行两个进程,这两个进程都会更新计数器。(它基本上实现了表的规范示例,如中所示 预期结果是,第一个进程的结果是增量为1,而第二个进

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

在这种情况下,我相信我看到了一些奇怪的
观察multi/exec
行为。具体地说,我预计两个事务中的一个会因为乐观锁定失败而失败(即,
watch
guard),但这两个事务似乎都没有发脾气,但会导致错误的最终值

为了说明,请参见下面的人为场景。它在节点中,但我相信这是一般的事情。这将并行运行两个进程,这两个进程都会更新计数器。(它基本上实现了表的规范示例,如中所示

预期结果是,第一个进程的结果是增量为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的监视器命令时,可以看到结果交错:

    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连接是否可以避免此问题?

回答我自己的问题:

这是预期的行为。第一个
exec
取消对所有属性的检查。因此,第二个
multi/exec
在没有监视保护的情况下通过

它在地下室,但它相当隐蔽


解决方案:使用多个连接,尽管有一些答案明确警告不要这样做,因为它(引号)“不需要”。在这种情况下,它是需要的。

什么是“错误的最终值”您得到的是?5或10?
incr
的值是
4
,在两个进程都增加后,该值是
5
。该值是预期值,但第二个事务应该失败,因为
incr
的值已从
4
更改为
5
,因此
监视
-guar第二个事务上的d应该失败。这不会happen@itamarHaber,可能就是这样。使用多个Redis连接,会正确导致watch guard失败。的dublicate