2013-02-14 39 views
15

私は静的で大きな(> 100M)、複雑なメモリ内のデータ構造にアクセスし、クエリを受け取り、そのデータの小さなスライスをHTTP経由でクライアントに提供するNodeアプリケーションを持っています。Node.JSのワーカー/スレッド/何かの間でメモリを共有する方法はありますか?

ほとんどのクエリは、10分の1秒で答えることができます。ノードのためのHurray!

しかし、特定のクエリでは、このデータ構造を検索するのに数秒かかります。他の誰もが待たなければならないので、これは吸う。

より多くのクライアントに効率的にサービスを提供するために、何らかの並列処理を使用したいと思います。

しかし、このデータ構造は非常に大きいので、私はそれをワーカーやスレッド間で共有したいのですが、何百メガバイトも焼き付けません。データ構造が書き込まれないため、これは完全に安全です。他の言語の典型的な 'fork()'がそれを行います。

しかし、私が知る限り、Nodeで並列処理を行うすべての標準的な方法は、これを明示的に不可能にしています。安全のために、あなたは何かを共有することを望んでいません。

しかし、方法はありますか?

背景:

データベースにこのデータ構造を置くことは現実的ではない、またはmemcachedの、またはそのようなものを使用します。

WebWorker APIライブラリなどでは、短いシリアライズされたメッセージだけがワーカーに出入りすることができます。

ノードのクラスタは 'fork'という名前のコールを使用しますが、実際には既存のプロセスのフォークではなく、新しいものを生成します。だからもう一度、共有メモリはありません。

本当に正しい答えは、共有メモリ、別名tmpfs、またはmmapへのファイルシステムのようなアクセスを使用することでしょう。このようなもののためにmount()とmmap()を利用できるいくつかのノードライブラリがあります。残念ながら、同期シークとリードの上に複雑なデータ構造のアクセスを実装する必要があります。私のアプリケーションでは、dictsなどの配列の配列を使用しています。すべてを再実装する必要がないのはいいことです。

+0

残りの部分をブロックしないように、(process.nextTickを使用して)検索を先取りできませんか? – robertklep

+3

'このデータ構造をデータベースに入れたり、memcachedなどを使うのは実用的ではありません。いつから? – freakish

+0

freakish:各アイテムがクエリのサブセットであるかどうかを確認しています。私たちが文字列 "fooquux"を持っているとしたら、その文字列に "ox"が含まれているかどうかチェックしたいとします。通常のデータベース操作で効率的に処理する方法はわかりません。しかし、通常のデータ構造としてアクセスできるのは簡単です。これらの多数のデータがソートされ、ランク付けされ、これらはデータの「ポインタ」であり、データ構造内にデータを持たない限り、実際的ではありません。 – NeilK

答えて

0

wafの建物は古いスタイル(ノード0.6以下)で、新しいビルドはgypです。

ノードクラスタ(http://nodejs.org/api/cluster.html)を見てください。これは詳細を知らなくても助けになるとはっきりしていませんが、forkを使って同じマシン上で複数のノードプロセスを実行します。

+1

クラスタは実際にはフォークしません。新しいプロセスを生成するだけです。私がフォークしたい理由は、私が知っている不変の記憶を共有することであり、子供たちによって変更されることはありません。 – NeilK

+2

あなたがリンクしているエントリから右:「これらの子ノードはまだV8の全く新しいインスタンスです。新しいノードごとに少なくとも30msの起動と10MBのメモリがあると仮定します。つまり、何千ものノードを作成することはできません。そして、私の場合、それぞれに100MBを超える負荷をかけなければなりません。 – NeilK

+0

@NeilK> 100MBは大したことではありません(ただし、100MBを超えると10GB:Dを理解しない限り)。より重要なのは、インスタンス間でデータを同期させることです。そのためには、そのデータを保持するために専用サーバーを使用することをお勧めします。私の答えを見てください。 – freakish

0

実際には、ノードはスポーンプロセスをサポートしています。私は、ノードのフォークが本当のフォークにどれだけ近いかわからないんだけど、あなたはそれを試すことができます。

http://nodejs.org/api/child_process.html#child_process_child_process_fork_modulepath_args_options

ところで:ノードがそのために不向きであることは事実ではありません。これは、他の言語/ Webサーバーと同じように適しています。サーバーの複数のインスタンスを異なるポートで起動し、プロキシを前面に配置することができます。

メモリがさらに必要な場合は、メモリを追加してください。 :)それはそれと同じくらい簡単です。また、RedisやMemcached(あるいは複雑なクエリが必要な場合はCouchbase)のような専用のメモリ内データベースにそのデータをすべて入れることも考えてください。そのデータを複製することについてもう心配する必要はありません。

+2

に。最後まで。 :)また、100Mのデータ構造のコピーをいくつかのプロセスに適度な予算で持たせることもできますが、私はこれを、無料のHeroku dyno(512 MBの制限があります)のサイドプロジェクトとして実行しています。二人の労働者が私の記憶予算を吹き飛ばし、Herokuはそれを止める。しかしもっと重要なことは、このような記憶を無駄にすることは私に怒りを与えます。 – NeilK

+0

あなたは算術演算を行うことができないと思うのですか?実際にはデータ構造は208 MBです - 100 MBは例でした – NeilK

+0

@NeilKしかし512MBの制限はあなたを怒らせませんか? :Dその他:forkの場合でも、子プロセスは読み取り専用でない限りデータをコピーします。 – freakish

5

nodejsからの共有メモリアクセスのC/C++バインディングを書きました。 https://github.com/supipd/node-shm

まだ作業中ですが(私のために働いています)、バグや提案があれば役に立つかもしれません。

+0

これは素晴らしいアイデア@supipdですが、現在のバージョンでこれを動作させることは可能でしょうか?私は 'node :: ObjectWrap'が新しいバージョンの' 'にリンクしていないと信じています。 (コンパイル時にユーザーにエラーが表示されます)とにかく、これが受け入れられる回答になるはずです。 :) –

0

ほとんどのWebアプリケーションは、ネットワークバッファとデータベースの読み取りを待っている間、ほとんどの人生を過ごしています。 Node.jsはこの縛られた作業で優れているように設計されています。あなたの仕事が本当にCPUに縛られているなら、あなたは別のプラットフォームによってより良いサービスを受けるかもしれません。道のうちそれと

...

  1. 使用process.nextTick(おそらくネストされたブロック)は、高価なCPUの作業が適切に非同期とあなたのスレッドをブロックすることが許可されていないことを確認します。これは、高価な要求をしているクライアントが他のすべてのクライアントに悪影響を及ぼさないようにします。

  2. node.jsクラスタを使用して、システムのCPUごとにワーカープロセスを追加します。ワーカープロセスはすべて単一のHTTPポートにバインドし、MemcachedまたはRedisを使用してメモリ状態を共有できます。ワーカーには、インプロセスメモリキャッシュを同期させるために使用できるメッセージングAPIもありますが、一貫性の制約があります。

関連する問題