nodejs, redis. check if keys exists and create new if not

落爺英雄遲暮 提交于 2019-12-01 19:05:55
Didier Spezia

There are at least two problems in this code:

  • the first one is linked to Javascript closure management. The body of a loop does not create a scope. With Javascript, scope of variables is at function level, not block level. You need to introduce some function in the loop itself to enforce the creation of a proper closure. More information here.

  • 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.

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.

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.

Example:

This program:

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)

displays:

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

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!