节点,Redis.检查密钥是否存在,如果不存在则创建新的 [英] nodejs, redis. check if keys exists and create new if not

查看:93
本文介绍了节点,Redis.检查密钥是否存在,如果不存在则创建新的的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm new to nodejs and maybe don't got an event system how it should work. Can't find a bug. Please advice. I need a simple task - check for a tag, if it does not exists, set the new key and info about the tag. The problem is - then I run the script for the first time, it's always returns 'keys not exists'. Check the redisdb keys - it creates many tags Here is my code

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"命令之后执行.所以...我明白,这都是因为异步操作.但如何让它发挥作用?

Looks like nodejs executes all 'get' commands and only after that 'set' commands. So... I understand, it's all because of async operations. But how to make it work?

推荐答案

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

There are at least two problems in this code:

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

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

the second one is a race condition between the exists and set commands. If you have several Redis connections running exists and set commands on the same keys, you will likely have some kind of conflicts. Instead of using exists and set, you should use setnx which perform the check and set in one atomic operation.

考虑您的第二个示例,闭包问题已通过使用 forEach 解决,但由于语言的异步性质,您仍然在设置操作之前生成所有获取操作.

Considering your second example, the closure problem has been fixed by using forEach, but you still generate all the get operations before the set operations due to the asynchronous nature of the language.

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

If you really want to sequence all your get and set operations (which will be much slower btw), then you can use a bit of functional programming to implement the loop using recursion.

示例:

这个程序:

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 来实现这种检查和设置操作.

Note that the race condition is still present in this example. You are supposed to use setnx to implement this kind of check and set operations.

这篇关于节点,Redis.检查密钥是否存在,如果不存在则创建新的的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆