13

アプリケーション用に memcached をデプロイしていますが、できる限り抵抗力のあるものにしたいと考えています。

新しいmemcacheD拡張機能を使用する予定です。

私が完全に把握していないことの 1 つは、サーバーの 1 つが停止した場合に何が起こるかということです。少なくとも、memcached クライアントはそのサーバーで「あきらめ」、何も保存しないようです。

この振る舞いは私は大丈夫です。大量のキャッシュミスに対処できます。ただし、サーバーの 1 つが「失敗」したと見なされた後、後続のセットが残りのサーバーに再配布されると便利です。

これは自動的には行われないようです。この問題に対処する唯一の方法は、外部システムに memcached システムのヘルスチェックを実行させ、サーバーのリストを適切に更新することだと思います。

しかし、10 台のサーバーのリストがあり、たとえば 5 番目のサーバーが死亡した場合..Ketama ハッシュを使用しても、これによりキーの大きな再配布がトリガーされるように思われます (これは常識に基づいています)。

したがって、理想的には、サーバーがダウンしていることを PHP 拡張機能が認識し、指定された時間 (10 分) の間ダウンしているとマークし、その 10 分間にセットと取得のために他のサーバー (適切に分散されている) にフォールバックするようにするだけです。 .

他の人はこれをどのように解決しますか?

編集:私のlibketamaポイントを明確にします。

10 台のサーバーがあるとします。

1,2,3,4,5,6,7,8,9,10

そのうちの1人が死亡します。Libketama は、見つからないサーバーへのヒットが残りのサーバーに均等に分散される可能性が非常に高いことを示します。

1,2,3,4,inactive,6,7,8,9,10

ただし、このリストを手動で提供および管理する場合は、そうではありません。

1,2,3,4,6,7,8,9,10 // There are now 9 servers!

6 は 5 の以前のキーを取得し、7 は 6 を取得します。8 は 7、9 は 8、10 は 9 になります。10 番目のサーバーが取得していたすべてのヒットは、残りのサーバーに均等に分散されません。その結果、すべてのキーのほぼ 50% が新しいサーバーに送信される可能性が高くなります。

4

4 に答える 4

3

私は通常、利用可能なサーバーのリストを APC に保存しているので、その場で変更できます。システムがリストされている間、ダウンしたサーバーを引き続き使用しようとするという点であなたは正しいです。幸いなことに、新しいハッシュ方法では、ローテーションからプルすることは大したことではありません.

まったく新しい PHP 拡張機能を使用したり、デプロイ スタックに新しいソフトウェアを追加しようとしたりすることは避けたいと思います。監視用に既に何かを使用している可能性があります (nagios?)。各 Web サーバーで単純な PHP スクリプトを呼び出して、メモリ内のリストを微調整するのが最善の策のようです。

Ketama ハッシュ システムの下では、サーバーをローテーションから削除すると、そのキーがリング (連続体) の他の場所で再ハッシュされることになり、他のサーバーは別の場所に割り当てられたキーを認識しません。円として視覚化します。各サーバーには円上の複数のポイント (100 ~ 200) が割り当てられます。キーはサークルにハッシュされ、サーバーが見つかるまで時計回りに続行されます。リングからサーバーを削除しても、これらの値は新しいサーバーを見つけるためにもう少し続けられます。運が良ければ、値の分布は残りのサーバーに均等にヒットします。

ハッシュ システムのデモンストレーション:

<?php


$m = new Memcached();
$m->setOption(Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_CONSISTENT);


$m->addServer('localhost', 11211);
$m->addServer('localhost', 11212);
$m->addServer('localhost', 11213);
$m->addServer('localhost', 11214);
$m->addServer('localhost', 11215);
$m->addServer('localhost', 11216);
$m->addServer('localhost', 11217);
$m->addServer('localhost', 11218);
$m->addServer('localhost', 11219);
$m->addServer('localhost', 11210);

$key = uniqid(); //You may change this to md5(uniqid()); if you'd like to see a greater variation in keys. I don't think it necessary.
$m->set($key, $key, 5);


var_dump($m->get($key));

unset($m);


$m = new Memcached();
$m->setOption(Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_CONSISTENT);
//one server removed. If assignment to the continuum is dependent based on add order, we would expect the get call here to fail 90% of the time, as there will only be a success if the value was stored on the first server. If the assignment is based on some hash of the server details we'd expect success 90% of the time. 
$m->addServer('localhost', 11211);
//$m->addServer('localhost', 11212);
$m->addServer('localhost', 11213);
$m->addServer('localhost', 11214);
$m->addServer('localhost', 11215);
$m->addServer('localhost', 11216);
$m->addServer('localhost', 11217);
$m->addServer('localhost', 11218);
$m->addServer('localhost', 11219);
$m->addServer('localhost', 11210);

var_dump($m->get($key));

unset($m);

$m = new Memcached();
$m->setOption(Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_CONSISTENT);
//2 servers removed
$m->addServer('localhost', 11211);
$m->addServer('localhost', 11212);
//$m->addServer('localhost', 11213);
//$m->addServer('localhost', 11214);
$m->addServer('localhost', 11215);
$m->addServer('localhost', 11216);
$m->addServer('localhost', 11217);
$m->addServer('localhost', 11218);
$m->addServer('localhost', 11219);
$m->addServer('localhost', 11210);

var_dump($m->get($key));

unset($m);

$m = new Memcached();
$m->setOption(Memcached::OPT_DISTRIBUTION, Memcached::DISTRIBUTION_CONSISTENT);
//Out of order
$m->addServer('localhost', 11210);
$m->addServer('localhost', 11211);
$m->addServer('localhost', 11219);
$m->addServer('localhost', 11212);
$m->addServer('localhost', 11217);
$m->addServer('localhost', 11214);
$m->addServer('localhost', 11215);
$m->addServer('localhost', 11216);
$m->addServer('localhost', 11218);
$m->addServer('localhost', 11219);
$m->addServer('localhost', 11213);

var_dump($m->get($key));

unset($m);

ハッシュシステムが順序を気にする場合、またはサーバーを省略した場合bool(false)、初期のサーバーが削除されたなどの理由で、ほとんどの二次的な例で取得できると予想されます。ただし、私の簡単な完全に非科学的なテストに基づいて、私は bool false のみを取得します任意の特定のスロットを 10 回に 1 回。テスト ボックスで 10 台のサーバーを起動したことは明らかです。それぞれに4MBのRAMのみを与える

于 2012-09-11T14:48:54.090 に答える
2

Memcached::OPT_AUTO_EJECT_HOSTSPHP のオプション定数を試してみたいと思うかもしれません。直接文書化されていませんが、ここに名前を付けたコメントがあります。

(私は試していないので、うまくいくかどうかはわかりません)

于 2012-09-11T14:49:29.303 に答える
0

私の 2 セント: Memcached 用の堅牢な HA モジュールを開発するのは簡単ではありません。たとえば、次のケースについて考えてみましょう。

  • どのサーバーが生きていて、どのサーバーが死んでいるかをどのように判断しますか? Web/アプリサーバーを実行しているすべての HA モジュール間で何らかの方法で同期する必要があります
  • Web/アプリ サーバー間でこの情報をどのように公開しますか
  • オーケストレーターはありますか?

Redis Sentinelをご覧になることをお勧めします。これは現在ベータ版であり、特に Redis でこれらの問題を解決するために、過去数か月間に開発およびテストされています。1 行のコードの開発を開始する前に知っておかなければならない多くのまれなケースがあります。

ここで議論された他の問題については:

  • ノードを失うと、キーの 1/N が失われます。ここで、N は最初に持っていたノードの数です。つまり、障害が発生したノードを含みます。これがケタマの仕組みです
  • 新しい Memcached クラスを使用して Memcached クライアントにキーを保存することは、間違いなく適切な方法ではありません (IMO): (1_ これらすべてのキーをどこに保存しますか? (2) Web/アプリ ノード間でどのように同期しますか? (3 ) 各キーがどのノードに存在するかを理解するために、これらのデータ構造にアクセスするのにどのくらいの時間がかかりますか? -- これが、Memcached が完全にハッシュ関数に基づいており、高速かつシンプルにする理由です。

最後になりましたが、Memcached as-a-service ソリューションも確認することをお勧めします。たとえば、Garantia Dataでは、Memcached の HA の問題を既に解決しています。

開示: 私は Garantia Data の共同創設者兼 CTO です。

于 2012-09-18T20:00:56.297 に答える
0

コメントへの回答に基づいて、次の行に沿って提案します。

キャッシュ クラスを作成する必要があります。

このクラスには次の情報が含まれます。

  • キャッシュサーバー一覧

    • オンラインまたはオフラインのステータス
    • このサーバーへのリクエスト数
  • 現在保存されているキーのリストとそれがどのサーバー上にあるか

次に、キーを追加、更新、および削除するための標準関数が必要になります。

これらの関数のいずれかを実行するたびに、キーが既にキャッシュにあるかどうか、およびどのサーバー上にあるかを確認する必要があります。

サーバーにない場合は、実際の DB 値を取得した後、リクエストが最も少ないサーバーを選択して保存します。

これらの関数のいずれかがキャッシュ サーバーからエラーを返した場合、そのサーバーをオフラインとしてマークし、カウントをリセットして、このサーバーにあるキーをリストから削除します。

この時点で、それらを新しいサーバーに自動的に移動するか、単に削除して、再度照会されるようにすることが簡単にできます。

于 2012-09-11T14:52:57.640 に答える