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

查看:601
本文介绍了nodejs,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一样,仅在该设置"命令之后才执行所有获取"命令.所以...我了解,这全都归因于异步操作.但是如何使其工作呢?

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,变量的范围是在函数级别上,而不是在块级别上.您需要在循环本身中引入一些函数来强制创建适当的闭包.更多信息此处.

第二个是存在和设置命令之间的竞争条件.如果存在多个正在运行的Redis连接,并在相同的键上设置命令,则可能会发生某种冲突.您应该使用 setnx 代替它的存在和设置,它执行检查并在一个原子操作中进行设置.

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解决了关闭问题,但是由于语言的异步特性,您仍然会在set操作之前生成所有get操作.

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.

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

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