简体   繁体   中英

Node & Redis: Redis Clients

Assume you have db's in Redis you would like to insert and/or remove data from. 数据库,您想插入和/或删除数据。 You have a flow like;

  • Insert data to
  • After the first insertion's do some stuff and insert data to 执行一些操作并将数据插入到
  • After the second insertion's do some stuff again and finally insert data to 再次执行一些操作,最后将数据插入到

I use one variable called that is basically created as; 变量,基本上创建为;

redisClient = redis.createClient();

And while selecting a new DB, I use command with the extra pre-caution callback, so my select command is like; 命令与格外小心前的回调,所以我选择指令等;

redisClient.select(1, function(err) {
  //Some programming logic (Insertion, deletion and stuff)
  redisClient.select(2, function(err) {
    //Do some additional programming logic (Insertion, deletion and stuff)
  }
});

However things get constantly mix. I would like to note that the redisClient variable has been assigned only once and later on used throughout the entire application. Now I was wondering, how reasonable would it be to use I have in Redis. 使用是多么合理。 So it would be like;

redisClientForDB1 = redis.createClient();
redisClientForDB2 = redis.createClient();
redisClientForDB3 = redis.createClient();

I was wondering would it be reasonable, or would it be a right way for an application that will receive and about to go to the production mode. 接收并即将进入生产模式的应用程序来说这是一种正确的方法。 What this model might face?

Just as Carl Zulauf said , it's best to open 3 different connections (one per DB):

redisClient = {
  DB1: redis.createClient(),
  DB2: redis.createClient(),
  DB3: redis.createClient()
};

It's best to open all connections once during the initialization of your server:

async.parallel([
  DB1.select.bind(DB1, 1),
  DB2.select.bind(DB2, 2),
  DB3.select.bind(DB3, 3)
], next);

So, after you created redisClient object and initialized it you can use it to handle all your redis operations.

If you'll use redis this way node will open 3 (and only 3) connections per node process.


NB It's also a good idea to put it all into one node module:

module.exports = {
  DB1: redis.createClient(),
  DB2: redis.createClient(),
  DB3: redis.createClient(),
  init: function(next) {
    var select = redis.RedisClient.prototype.select;
    require('async').parallel([
      select.bind(this.DB1, 1),
      select.bind(this.DB2, 2),
      select.bind(this.DB3, 3)
    ], next);
  }
};

Then you'll be able to initialize all your redis connections by calling init function once (because node caching require calls):

require('./lib/my_redis').init(function(err) {
  if (err) throw err;
  server.listen();
});

Then when require('./lib/my_redis').DB1.set('key','val') will be called in any of your modules DB1 will be already initialized.

Using 3 connections for 3 different databases is the correct approach. There is overhead for having additional connections open, but that overhead is very small.

With something like hundreds of open connections the overhead would start to be a problem. I'm not sure how many instances of your app you will run but guessing at just 3 connections per process you won't get anywhere near problematic numbers.

If Google brought you here, do yourself a favour: don't use multiple DB support. Use namespaced keys or multiple redis instances.

I say this after having struggled with multiple DB support in an async environment myself. At wits end, I visited #redis on Freenode and was referred to the following statement by Redis' author, Salvatore Sanfilippo:

I consider Redis multiple database errors my worst decision in Redis design at all... I hope that at some point we can drop the multiple DBs support at all, but I think it is probably too late as there is a number of people relying on this feature for their work.

https://groups.google.com/d/msg/redis-db/vS5wX8X4Cjg/8ounBXitG4sJ

You really want to think twice before relying on the feature the author regrets the most.

您可以使用MULTI/EXEC块来代替3个不同DB的3个不同连接:

redisClient.multi().select(1).set("my_key_in_db_1","myval").exec()

Using one instance for each database is the correct approach. But if you need to reuse or throttle expensive resources such as database connections, then a database connection pool could be a good choice. Let's say we choose generic-pool (a generic pooling solution for node.js), you can code like this:

// Step 1 - Create pool using a factory object
var mysql= require('mysql'),
    generic_pool = require('generic-pool');

var pool = generic_pool.Pool({
    name: 'mysql pool 1',
    min: 1,
    max: 50,
    idleTimeoutMillis : 30000,
    create   : function(callback) {
        var Client = mysql.Client;
        var c = new Client();
        c.user     = 'myusername';
        c.password = 'mypassword';
        c.database = 'mydb';
        c.connect();

        callback(null, c);
    },
    destroy  : function(client) { client.end(); }
});

// Step 2 - Use the pool in your code to acquire/release resources
pool.acquire(function(err, client) {
    if (err) {
        // handle error
        return res.end("CONNECTION error: " + err);
    }
    client.query("select * from foo", [], function() {
        // return object back to pool
        pool.release(client);
    });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM