node.js - Node ,redis。检查 key 是否存在,如果不存在则创建新的

标签 node.js redis key exists

我是 nodejs 的新手,可能不知道事件系统应该如何工作。 找不到错误。请指教。 我需要一个简单的任务——检查一个标签,如果它不存在,设置新的 key 和关于标签的信息。 问题是 - 然后我第一次运行脚本,它总是返回“ key 不存在”。检查 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”命令之后执行。所以...我明白了,这都是因为异步操作。但是如何让它发挥作用呢?

最佳答案

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

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

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

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

如果您真的想对所有 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 来实现这种检查和设置操作。

关于node.js - Node ,redis。检查 key 是否存在,如果不存在则创建新的,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11000911/

相关文章:

node.js - 使用 Nginx 作为 Node.js 的代理向 favicon.ico 添加 Expires header

node.js - 删除模块目录后 npm install 不再可能

redis - redisson outofDirectMemory 异常

java - Android 无法触发 onKey 事件

json - JQ:如何根据正则表达式匹配替换键和值?

c++ - 如何在 Allegro 的屏幕上从键盘输入?

node.js - Mongoose 私有(private)集场

mysql - Sequelize 将表创建迁移到关联不起作用的空数据库中

haskell - 何时(何时不)定义 Monad

python - 如何在 Heroku(使用 python)上的 web 和 worker(不同的 dynos)之间通信数据?