【问题标题】:nodejs, redis. check if keys exists and create new if not节点,redis。检查密钥是否存在,如果不存在则创建新的
【发布时间】:2012-06-15 14:04:14
【问题描述】:

我是 nodejs 的新手,可能不知道它应该如何工作的事件系统。 找不到错误。请指教。 我需要一个简单的任务 - 检查标签,如果它不存在,设置新的密钥和有关标签的信息。 问题是 - 然后我第一次运行脚本,它总是返回“键不存在”。检查 redisdb 键 - 它创建了许多标签 这是我的代码

for (x = 0; x < rows.length; x++) {
    if (rows[x].term_taxonomy_id != 1) {
        var taxonomy = findOne(rterms, rows[x].term_taxonomy_id);
        rc.exists('tag:' + taxonomy.name, function (err, rexists) {
            if (rexists == false) {
                rc.incr('tags:count', function (err, id) {
                    console.log(taxonomy.name+' not exists. result ' + rexists);
                    rc.set('tag:' + taxonomy.name,id);
                    rc.hmset('tag:' + id,
                        'id', id,
                        'title',taxonomy.name,
                        'url', taxonomy.slug
                    );
                });//incr
            }else{
                console.log(taxonomy.name+' exists!'+rexists);
            };
        });//exists
    };//ifrows
});

这是另一个例子

var tags = [
  "apple",
  "tiger",
  "mouse",
  "apple",
  "apple",
  "apple",
  "tiger",
  "mouse",
  "mouse",
];
var count =0;
Object.keys(tags).forEach (function (tag) {
  rc.get("tag:"+tags[tag],function(err,rr){
    console.log("get tag "+tags[tag]+" result code "+rr);
    if (rr == null) {
      rc.set("tag:"+tags[tag],"info",function(err,rr){
        count++;
        console.log('set tag '+tags[tag]+' '+rr+' objects count '+count);
      });
    };
  });
})

输出:

get tag apple result code null
get tag tiger result code null
get tag mouse result code null
get tag apple result code null
get tag apple result code null
get tag apple result code null
get tag tiger result code null
get tag mouse result code null
get tag mouse result code null
set tag apple OK objects count 1
set tag tiger OK objects count 2
set tag mouse OK objects count 3
set tag apple OK objects count 4
set tag apple OK objects count 5
set tag apple OK objects count 6
set tag tiger OK objects count 7
set tag mouse OK objects count 8
set tag mouse OK objects count 9

看起来 nodejs 执行所有“get”命令,并且仅在“set”命令之后执行。所以......我明白,这都是因为异步操作。但是如何让它发挥作用呢?

【问题讨论】:

    标签: node.js redis key exists


    【解决方案1】:

    这段代码至少有两个问题:

    • 第一个链接到 Javascript 闭包管理。循环体不会创建范围。使用 Javascript,变量的范围是函数级别,而不是块级别。您需要在循环本身中引入一些函数来强制创建正确的闭包。更多信息here

    • 第二个是存在和设置命令之间的竞争条件。如果您有多个 Redis 连接运行并在相同的键上设置命令,您可能会遇到某种冲突。您应该使用setnx,而不是使用存在和设置,它在一个原子操作中执行检查和设置。

    考虑到您的第二个示例,已通过使用 forEach 解决了闭包问题,但由于语言的异步特性,您仍然会在 set 操作之前生成所有 get 操作。

    如果您真的想对所有 get 和 set 操作进行排序(顺便说一句,这会慢得多),那么您可以使用一些函数式编程来使用递归来实现循环。

    示例

    这个程序:

    var redis = require('redis')
    var rc = redis.createClient(6379, 'localhost');
    
    var tags = [
      "apple",
      "tiger",
      "mouse",
      "apple",
      "apple",
      "apple",
      "tiger",
      "mouse",
      "mouse",
    ];
    
    var count = 0;
    
    function loop(tags) {
      function rec_loop(tags,i) {
         if ( i >= tags.length )
            return
         rc.get("tag:"+tags[i],function(err,rr) {
            console.log("get tag "+tags[i]+" result code "+rr);
            if ( rr == null ) {
               rc.set("tag:"+tags[i],"info",function(err,rr) {
                  count++;
                  console.log('set tag '+tags[i]+' '+rr+' objects count '+count);
                  rec_loop(tags,++i)
               })
            } else
              rec_loop(tags,++i)
         })
      }
      rec_loop(tags,0)
    }
    
    loop(tags)
    

    显示:

    get tag apple result code null
    set tag apple OK objects count 1
    get tag tiger result code null
    set tag tiger OK objects count 2
    get tag mouse result code null
    set tag mouse OK objects count 3
    get tag apple result code info
    get tag apple result code info
    get tag apple result code info
    get tag tiger result code info
    get tag mouse result code info
    get tag mouse result code info
    

    请注意,此示例中仍然存在竞争条件。您应该使用 setnx 来实现这种检查和设置操作。

    【讨论】:

    • 谢谢。我确定程序执行流程中的问题。我又做了一次测试,遇到了同样的问题。
    • 在我之前的回复中添加了一个例子。
    • 感谢您提供这个很好的例子。经过多年的线性编程,想异步有点困难。
    猜你喜欢
    • 2014-07-23
    • 2020-08-19
    • 2016-05-14
    • 2011-05-12
    • 2011-09-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多