Memcachedクラスタリングとキャッシュキーの選択

「Web、キャッシング、memcached」という一般的なタイトルでの一連の投稿は続きます。 最初に、 memcached、そのアーキテクチャ、および可能な用途について説明しました。



今日は以下についてお話します:



次の投稿では、 memcachedの操作とカウンターの原子性について説明します。





キャッシングキー



キャッシングにmemcachedを使用することが適切なソリューションであることをすでに確認してみましょう。 直面する最初のタスクは、各キャッシュのキーの選択です。 memcachedのキーは、限られた長さの文字列で、限られた文字セットで構成されています(たとえば、スペースは禁止されています)。 キャッシュキーには次のプロパティが必要です。



もちろん、各サンプルのキーを個別に作成することもできます。たとえば、ID 158のユーザー情報を取得する'friends_192_public_sorted_online'



や、ID 192のユーザーの友人の'friends_192_public_sorted_online'



を公​​開できます。 このようなアプローチには、エラーと上記で作成された条件への非準拠が伴います。



次のオプション(PHPの例)を使用できます:データベースへのすべての呼び出しが通過するコードにポイントがあり、すべての呼び出しが一部の$options



構造に完全に記述されている(すべての要求パラメーターを含む)場合、次のキーを使用できます:



 $key = md5(serialize($options))
      
      





このようなキーは間違いなく最初の条件を満たします( $options



が変更されると、 $key



は必ず変更されます)が、$オプションのすべてのデータ型を「標準的に」使用すると、2番目の条件も満たされます。 数字の1



代わりに文字列"1"



許可しないでください(PHPではこのような2つの値は同じですが、シリアル化された表現は異なります)。 md5



関数は、データを「圧縮」するために使用されます。memcachedキーには長さの制限があり、シリアル化されたビューが長すぎる可能性があります。



Memcachedクラスタリング



単一のmemcachedサーバーの代わりに、このようなサーバーのクラスターを使用して負荷を分散し、フォールトトレランスを実現します。 クラスターに含まれるサーバーは、異なる量のメモリで構成でき、合計キャッシュサイズは、クラスターのすべてのmemcachedメンバーのキャッシュサイズの合計に等しくなります。 memcachedプロセスは、プロセッサの使用率が低く、ネットワークが制限までロードされていないサーバー(ファイルサーバーなど)で開始できます。 プロセッサの負荷が高いと、memcachedは要求に十分に迅速に応答できない可能性があり、サービスの低下につながります。



クラスターで作業する場合、キーはサーバー間で分散されます。つまり、各サーバーはプロジェクトキーの合計配列の一部を処理します。 フォールトトレランスは、サーバーの1つに障害が発生した場合、キーが残りのクラスターサーバーに再配布されるという事実に基づいています。 もちろん、この場合、障害が発生したサーバーのコンテンツは失われます(「キーの損失」セクションを参照)。 必要に応じて、重要なキーを1つのサーバーではなく複数のサーバーに保存できるため、ストレージの冗長性によるサーバークラッシュの影響を最小限に抑えることができます。



クラスタリングでは、キー配布の問題が重要になります。サーバー間でキーを最も効率的に配布する方法です。 これを行うには、キー配布機能を決定する必要があります。キー配布機能は、キーによって保管先のサーバー番号(または、ストレージが冗長で発生する場合はサーバー番号)を返します。



歴史的に、最初の分布関数はモジュール関数でした:



 f() = crc32() % _
      
      





このような機能により、サーバー間でキーが均一に分散されますが、memcachedクラスターを再構成すると問題が発生します。サーバーの数を変更すると、サーバー間でキーの大部分が移動し、キーの大部分が失われることになります。



この機能の代替手段は、一貫したハッシュメカニズムです。これは、クラスターを再構成するときに、サーバー全体でキーの位置を保持します。 このアプローチは、2007年4月にLast.fm開発者によってmemcachedクライアントに最初に実装されました。







アルゴリズムの本質は次のとおりです。0から2 32までの整数のセットを考え、数値軸をリングに「ねじり」ます(0と2 32を接着します)。 memcachedサーバーのプールから各サーバーに、リング上の番号を関連付けます(左側の図、サーバーA、B、C)。 キーは同じ範囲の数字にハッシュされます(図の青い点1〜4)。キーを保存するサーバーとして、時計回りにキーポイントに最も近いポイントにあるサーバーを選択します。 サーバーがプールから削除されるか、プールに追加されると、サーバーポイントが軸上に表示または非表示になり、その結果、キーの一部のみが別のサーバーに移動されます。 右側の図2は、サーバーCがサーバープールから削除され、新しいサーバーDが追加されたときの状況を示しています。キー1と2がサーバーへのバインドを変更せず、キー3と4が他のサーバーに移動したことがわかります。 実際、軸上の100〜200ポイントが1つのサーバーに割り当てられ(プール内の重みに比例)、構成が変更された場合にサーバー全体でキーの分散の均一性が向上します。



このアルゴリズムは、さまざまなプログラミング言語の多くのmemcachedクライアントに実装されていますが、実装の詳細が異なる場合があり、ハッシュの非互換性につながります。 このため、さまざまなプログラミング言語からmemcachedサーバーの同じプールにアクセスする場合、一貫したハッシュを使用するのは不便です。 crc32とモジュールを使用した最も単純なアルゴリズムは、すべての言語のすべてのクライアントに同じ方法で実装され、サーバー上で同じキーハッシュを保証します。 したがって、異なるプログラミング言語のさまざまなクライアントからmemcachedにアクセスする必要がない場合、一貫したハッシュを使用するアプローチがより魅力的に見えます。



素材

  1. http://weblogs.java.net/blog/tomwhite/archive/2007/11/consistent_hash.html
  2. http://www.lastfm.ru/user/RJ/journal/2007/04/10/rz_libketama_-_a_consistent_hashing_algo_for_memcache_clients



All Articles