15

データを挿入および/または削除したい Redis に複数のデータベースがあるとします次のような流れがあります。

  • DB #1にデータを挿入する
  • 最初の挿入のコールバックの後、いくつかのことを行い、 DB #2にデータを挿入します
  • 2 番目の挿入のコールバックの後、もう一度何かを行い、最後にデータをDB #3に挿入します。

基本的に次のように作成されるredisClientという1 つの変数を使用します。

redisClient = redis.createClient();

そして、新しい DB を選択している間、私はselectコマンドを追加の事前注意コールバックと共に使用するので、私の select コマンドは次のようになります。

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)
  }
});

しかし、物事は常に混ざり合っています。redisClient 変数は一度だけ割り当てられ、その後アプリケーション全体で使用されることに注意してください。Redis にあるDB ごとに個別の redisClientsを使用するのがどれほど合理的か疑問に思っていました。つまり、次のようになります。

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

それが妥当なのか、それとも毎秒 4K のリクエストを受信して​​本番モードに移行しようとしているアプリケーションにとって正しい方法なのか、疑問に思っていました。このモデルはどのような問題に直面する可能性がありますか?

4

5 に答える 5

14

Carl Zulauf が言ったように、3 つの異なる接続 (DB ごとに 1 つ) を開くのが最善です。

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

サーバーの初期化中にすべての接続を 1 回開くことをお勧めします。

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

したがって、redisClientオブジェクトを作成して初期化したら、それを使用してすべての redis 操作を処理できます。

この方法で redis を使用すると、ノードはノード プロセスごとに 3 つ (そして 3 つだけ) の接続を開きます。


: すべてを 1 つのノード モジュールに入れることもお勧めします。

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);
  }
};

次に、関数を 1 回呼び出すことで、すべての redis 接続を初期化できますinit(ノード キャッシングrequire呼び出しのため)。

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

次にrequire('./lib/my_redis').DB1.set('key','val')、モジュールのいずれかでいつ呼び出されるかは、DB1すでに初期化されています。

于 2013-01-02T19:12:26.330 に答える
11

3 つの異なるデータベースに対して 3 つの接続を使用するのが正しいアプローチです。追加の接続を開くためのオーバーヘッドがありますが、そのオーバーヘッドは非常に小さいです。

何百もの開いている接続のようなものでは、オーバーヘッドが問題になり始めます。アプリのインスタンスをいくつ実行するかはわかりませんが、プロセスごとに 3 つの接続しかないと推測すると、問題のある数には近づきません。

于 2012-12-22T21:10:18.140 に答える
7

もし Google があなたをここに連れてきたのなら、あなた自身に好意を持ってください: 複数の DB サポートを使わないでください。名前空間付きのキーまたは複数の Redis インスタンスを使用します。

これは、非同期環境での複数の DB サポートに苦労した後に言います。最後に、私は Freenode の #redis にアクセスし、Redis の作成者である Salvatore Sanfilippo による次の声明を参照しました。

Redis の複数のデータベース エラーは、Redis 設計における最悪の決定だと思います... ある時点で、複数の DB のサポートを完全に廃止できることを願っていますが、多くの人が依存しているため、おそらく遅すぎると思います。彼らの仕事のためのこの機能。

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

作成者が最も後悔している機能に頼る前に、よく考えてください。

于 2013-07-10T14:01:36.223 に答える
2

3 つの異なる DB に対して 3 つの異なる接続を持つ代わりに、MULTI/EXECブロックを使用することもできます。

redisClient.multi().select(1).set("my_key_in_db_1","myval").exec()
于 2013-01-02T16:14:24.000 に答える
1

データベースごとに 1 つのインスタンスを使用するのが正しいアプローチです。ただし、データベース接続などの高価なリソースを再利用または調整する必要がある場合は、データベース接続プールが適しています。generic-pool (node.js の汎用プーリング ソリューション)を選択するとします。次のようにコーディングできます。

// 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);
    });
});
于 2013-01-04T06:14:47.617 に答える