所有 Redis 命令都是异步的吗?

Posted

技术标签:

【中文标题】所有 Redis 命令都是异步的吗?【英文标题】:Are all Redis Commands Asynchronous? 【发布时间】:2016-01-16 03:35:59 【问题描述】:

我是 Redis 和 Node.JS 的新手,一直在尝试将两者结合使用。但是我有点困惑,我可以一个接一个地使用哪些功能。

以下代码似乎是同步运行的,随着数据库大小的增加:

client.dbsize(function(err, numKeys) 
  console.log("DB Size before hashes added" + numKeys);
  return numKeys;
);

for (var i = 0; i < 100; i++) 
  client.hmset(i, "username", "username", "answer", "answer");
  client.zadd('answer', i, i);
;

client.dbsize(function(err, numKeys) 
  console.log("DB Size after hashes added" + numKeys);
  return numKeys;
);

但是,当我尝试查询已排序的集合“answer”以返回一个数组时,该数组“reply”不能立即用于“zrevrangebyscore”回调之外的其他 redis 函数。

client.zrevrangebyscore('answer', 100, 0, function(err, reply) 
  console.log (reply);
  return reply;
);

例如,在回复[1] 上调用的后续“hgetall”函数返回未定义。我应该通过回调/client.multi 等异步方式使用所有 Redis 函数(包括 hmset 和 dbsize),或者如果同步使用,则可以有效地工作?感谢所有帮助。

【问题讨论】:

【参考方案1】:

当谈到同步和异步代码时,您似乎很困惑。我建议您尽可能多地阅读,直到它“点击”为止。 我将举例说明问题所在以及原因:

//we're going to fake the redis dbSize function
var dbSize = function(callback)
  //always finishes asynchronously
  console.log("dbsize called");
  setTimeout(callback, 1000);
;

//here we get to your code
dbSize(function()
  console.log("First callback");
);

console.log("synchronous redis method calls");
//here come the synchronous redis methods, that finish synchronously

dbSize(function()
  console.log("Second callback");  
);

现在,如果您 run this code 它会向控制台输出以下内容:

"dbsize called"
"synchronous redis method calls"
"dbsize called"
"First callback"
"Second callback"

如您所见,同步方法被调用,异步方法完成。所以,所有要做的就是确保您调用同步方法之后,这将在第一个回调中,即您必须将这些东西链接在一起。 现在这很混乱,因为它会将您带入回调地狱:

dbSize(function()

    console.log("First callback");

    console.log("synchronous redis method calls");
    //here come the synchronous redis methods, that finish synchronously

    dbSize(function()
      console.log("Second callback");  
    );
)

因此,为避免这种情况,最好使用 async lib 之类的东西

async.series([
    function(next)
        dbSize(next);
    ,
    function(next)
        console.log("synchronous redis method calls");
        //here come the synchronous redis methods, that finish synchronously
        next();            
    ,
    function(next)
        dbSize(next);
    ,
], function()
    console.log('All done!');
)

这将输出:

"dbsize called"
"synchronous redis method calls"
"dbsize called"
"All done!"

【讨论】:

感谢您的回答,帮了大忙!【参考方案2】:

Redis is single-threaded,所以Redis 上的命令总是按顺序执行。看起来您可能正在为 Redis 使用异步客户端,这就是混乱的来源。因为您无法保证网络延迟,所以如果您使用异步 Redis 客户端,则稍后的调用可能会在之前的调用之前到达 Redis 服务器并导致您遇到问题。对于 Redis 的异步客户端为什么存在 here,有一个很好的解释。

综上所述,在您的案例中,重要的一点是,如果您希望您的命令保证同步运行,您有几个选择:

    在 Redis 中使用 pipeline 可以让您的所有命令只与服务器进行一次往返(无论如何,这可能是个好主意,除非您需要在命令之间做一些事情)。 使用异步库,如文档中的 here。 使用同步 Redis 客户端。我对 Node.js 的了解还不够,无法知道它的可行性。

【讨论】:

感谢您的回答,帮了大忙!

以上是关于所有 Redis 命令都是异步的吗?的主要内容,如果未能解决你的问题,请参考以下文章

Node.js Array.map() 是异步的吗?

memcached是原子的吗

异步 redis 和承诺

列名应该在所有表中都是唯一的吗?

评论在所有主要环境中都是 100% 安全的吗?

所有 PHP 相等比较都是对称的吗?