このページでは、App Engine memcache サービスの概要を説明します。高パフォーマンスでスケーラブルなウェブ アプリケーションでは多くの場合、一部のタスクの処理に、堅牢で永続的なストレージに優先して(あるいはその代わりに)分散型のインメモリ データ キャッシュを使用します。App Engine にメモリ キャッシュ サービスが含まれているのはそのためです。memcache サービスの構成、モニタリング、使用方法については、memcache の使用をご覧ください。
メモリ キャッシュの用途
メモリ キャッシュの 1 つの用途は、一般的なデータストア クエリを高速化することです。多くのリクエストが、同じパラメータを使用して同じクエリを実行し、結果への変更をすぐにウェブサイトに表示する必要がない場合、アプリは memcache に結果をキャッシュに保存できます。後続のリクエストで、Memcache をチェックし、結果が存在しないか、または期限が切れている場合にのみ、データストア クエリを実行できます。セッション データ、ユーザー設定、およびウェブページへのクエリによって返されたその他のデータは、キャッシュに適した候補です。
Memcache は他の一時的な値にも便利です。ただし、memcache のみに値を保存し、他の永続ストレージを使用しないかどうかを検討する場合、値が突然使用できなくなったときに、アプリケーションが適切に動作するようにしてください。値はいつでも memcache で期限切れになる可能性があり、値に設定された有効期限よりも前に期限切れになる可能性もあります。たとえば、ユーザーのセッション データが突然なくなったために、セッションが誤動作する場合、そのデータはおそらく memcache に加えて、データストアにも保存する必要があると考えられます。
サービスレベル
App Engine は 2 つのレベルの memcache サービスをサポートしています。
共有 memcache は App Engine アプリケーションの無料のデフォルトです。これは、ベストエフォート方式でキャッシュ容量を提供し、共有 memcache サービスを使用するすべての App Engine アプリケーションの総需要に基づきます。
専用 memcache は、アプリケーションに排他的に割り当てられた固定キャッシュ容量を提供します。これはキャッシュ サイズの GB/時間に応じて課金されるため、課金を有効にする必要があります。キャッシュ サイズを管理することで、アプリの実行に対する予測可能性が向上し、よりコストがかかる長期保存用のストレージからの読み取りを減らすことができます。
どちらの memcache サービスレベルも同じ API を使用します。アプリケーション用に memcache サービスを構成するには、memcache の使用をご覧ください。
次の表に、2 つのクラスの memcache サービスの違いをまとめています。
機能 | 専用 Memcache | 共有 Memcache |
---|---|---|
料金 | $0.06/GB/時間 | 無料 |
容量 |
|
保証された容量なし |
パフォーマンス | 最大 10,000 読み取りまたは 5,000 書き込み(排他的)/秒/GB(1 KB 未満のアイテム)。詳しくはキャッシュ統計をご覧ください。 | 保証なし |
長期保存 | × | × |
SLA | なし | なし |
専用 Memcache の料金は、15 分単位で課金されます。米ドル以外の通貨でお支払いの場合は、Cloud Platform SKU に記載されている該当通貨の料金が適用されます。
アプリでさらに多くの Memcache 容量が必要な場合は、Google のセールスチームまでお問い合わせください。
制限
memcache サービスの使用には次の制限が適用されます。
- キャッシュに保存されるデータ値の最大サイズは、1 MiB(2^20 バイト)から、キーのサイズと実装に依存するオーバーヘッド(約 73 バイト)を差し引いた値になります。
- キーは 250 バイト以下にしてください。Java ランタイムでは、250 バイトより長いオブジェクトや文字列のキーはハッシュされます(他のランタイムの動作は異なります)。
- 「マルチ」バッチ処理では、任意の数の要素を使用できます。呼び出しの合計サイズとフェッチされるデータの合計サイズが 32 MB を超えないようにする必要があります。
- memcache キーには NULL バイトを格納できません。
推奨事項とベスト プラクティス
Memcache を使用する場合は、次のようにアプリケーションを設計することをおすすめします。
キャッシュに保存された値が常に利用できないケースに対処する。
- Memcache は耐久性の高いストレージではありません。エビクション ポリシーに従って、キャッシュがいっぱいになると、キーが強制排除されます。キャッシュの構成の変更またはデータセンターのメンテナンス時にもキャッシュの一部またはすべてがフラッシュされる可能性があります。
- Memcache が一時的に使用できなくなる場合があります。Memcache オペレーションは、キャッシュ構成の変更やデータセンターのメンテナンス イベントなど、さまざまな理由で失敗することがあります。アプリケーションは、エラーをエンドユーザーに通知せずに、失敗したオペレーションをキャッチするように設計されている必要があります。このガイダンスは Set オペレーションに特にあてはまります。
できるだけ API のバッチ機能を使用します。
- そうすることで、特に小さなアイテムにおいて、アプリのパフォーマンスと効率が向上します。
memcache キースペース全体で負荷を分散します。
不均一なトラフィックの量を 1 つまたは小さな memcache アイテムのセットで表すことはアプリのスケーリングを妨げます。このガイダンスはオペレーション数/秒と帯域幅の両方にあてはまります。多くの場合、データの明示的なシャーディングによって、この問題を軽減できます。
たとえば、頻繁に更新されるカウンタを複数のキーに分割し、合計が必要な場合にのみ読み取り、合算できます。同様に、読み取る必要がある 500 K のデータを複数のキーにまたがる各 HTTP リクエストに分割し、1 つのバッチ API 呼び出しを使用して、それらを読み取ることが可能です(インスタンス メモリ内に値をキャッシュ保存した方がよい場合もあります)。専用 memcache の場合、単一キーのピークアクセス レートは、GB ごとの評価より 1、2 桁小さくなるはずです。
キャッシュから値を取得するために独自のキーを保持する。
- Memcache にはキーを一覧表示するメソッドがありません。キャッシュの性質上、キャッシュを中断せずにキーを一覧表示することはできません。また、Python などの一部の言語、ハッシュ長のキー、元のキーはアプリケーションのみが認識できます。
使用可能な API
App Engine memcache は低レベル Memcache API と JCache 仕様の 2 つのインターフェースをサポートしています。次のセクションで、各インターフェースに関する詳細を説明します。
低レベル API
低レベル Memcache API は JCache と比較して多くの機能をサポートしています。次に例を示します。
- 整数カウンタ値をアトミックに増減します。
- 最も長い間使われていないエントリがアクセスされてからの時間やキャッシュ内の全アイテムの合計サイズなど、多くのキャッシュ統計情報を公開します。
- データを条件付きで格納するためのチェック オペレーションと設定オペレーション。
- AsyncMemcacheService を使用して、memcache オペレーションを非同期で実行します。
低レベル API には、memcache サービスにアクセスするための MemcacheService
と AsyncMemcacheService
が用意されています。この API は、JCache よりも高度な機能を備えています。
低レベル Memcache API の同期および非同期使用の例については、memcache の例を参照してください。
JCache
App Engine Java SDK は、JCache API をサポートしています。JCache は、キャッシュされたデータに対してマップに似たインターフェースを備えています。キャッシュに値を格納したり、キャッシュ内の値を取得したりするにはキーを使用します。キーと値には、シリアル化可能な任意の型またはクラスを指定できます。詳しくは、memcache の使用をご覧ください。
JCache 機能はサポートされていない
JCache は次の機能をサポートしていません。
- JCache listener API は
onPut
およびonRemove
リスナーなどのアプリの API 読み出しの処理中に実行可能なリスナーについて部分的にサポートされています。バックグラウンド処理を必要とするリスナー(onEvict
など)はサポートされていません。 - アプリは、キャッシュに特定のキーが格納されているかどうかをテストできますが、キャッシュに特定の値が格納されているかどうかをテストすることはできません(
containsValue()
はサポートされていません)。 - アプリはキャッシュのキーや値の内容をダンプできません。
- アプリはキャッシュ統計を手動でリセットできません。
put()
メソッドはキーの以前の既知の値を返しません。常にnull
が返されます。
キャッシュに保存されたデータの期限切れ
memcache には Key-Value ペアが格納されます。アイテムがキャッシュに書き込まれたり、キャッシュから取得されたりするため、メモリ内のペアはいつでも変更されます。
デフォルトで memcache に保存される値は、可能な限り長く保持されます。キャッシュに新しい値が追加され、キャッシュのメモリが不足すると、キャッシュから値が強制排除されます。メモリ圧縮のために値が強制排除されると、最も長く使用されていない値が最初に強制排除されます。
アプリでは、値が追加されたときからの相対秒数か、または将来の絶対 Unix エポック時間(1970 年 1 月 1 日午前 0 時からの秒数)のいずれかで、値が保存される有効期限を設定できます。値はこの時間までに強制排除されますが、他の理由でもっと早く強制排除されることがあります。既存のキーに格納されている値をインクリメントしても、その有効期限は更新されません。
まれに、メモリ圧縮以外の理由で、有効期限の前にキャッシュから値が消失することもあります。memcache はサーバーの障害に対する復元性がありますが、memcache の値はディスクに保存されないため、サービスの障害によって、値が使用できなくなることがあります。
一般に、アプリケーションでは、キャッシュに保存された値が常に使用できるものと期待するべきではありません。
API を使用するか、または Google Cloud Console の Memcache セクションでアプリケーションのキャッシュ全体を消去できます。
キャッシュ統計
アイテムサイズ別の 1 秒あたりのオペレーションの回数
専用 Memcache は 1 GB ごとの 1 秒あたりのオペレーションの回数で評価されます。ここでオペレーションとは、get
、set
、または delete
など、キャッシュ アイテムへの個別のアクセスとして定義されます。オペレーション数はだいたい次の表に従い、アイテムサイズによって異なります。これらの評価を超えると、API のレイテンシの増加またはエラーが発生する可能性があります。
次の表にキャッシュの GB あたりの継続的な排他的 get-hit
または set
オペレーションの最大数を示します。get-hit
オペレーションは指定したキーで保存された値があることを検出し、その値を返す get
呼び出しです。
アイテムサイズ(KB) | 最大 get-hit オペレーション数/秒 |
最大 set オペレーション数/秒 |
---|---|---|
1 以下 | 10,000 | 5,000 |
100 | 2,000 | 1,000 |
512 | 500 | 250 |
数 GB のキャッシュが構成されているアプリは、理論上 GB 数と GB あたりのレートを乗算した数値として計算される合計オペレーション数を実現できます。たとえば、5 GB のキャッシュで構成されたアプリは 1 KB のアイテムで 50,000 memcache オペレーション数/秒に到達する可能性があります。このレベルを実現するには、Memcache キースペース全体で負荷を適切に分散する必要があります。
各 IO パターンで、上記の上限は読み取りまたは書き込みに対するものです。読み取りおよび書き込みを同時に行った場合、上限がスライドします。つまり、読み取りの実行が多くなると書き込みは減少し、書き込みが増加すると読み取りは減少します。1 GB のキャッシュあたりの 1 KB の値の読み書きを同時に行った場合の IOPS の上限の例を次に示します。
読み取り IOPS | 書き込み IOPS |
---|---|
10,000 | 0 |
8,000 | 1,000 |
5,000 | 2,500 |
1,000 | 4,500 |
0 | 5,000 |
Memcache コンピューティング単位数(MCU)
memcache のスループットはアクセスしているアイテムのサイズおよびアイテムに対して行うオペレーションによって異なることがあります。コストとオペレーションはほぼ関連付けることができ、Memcache コンピューティング単位数(MCU)という単位を使用して、専用 memcache から予想できるトラフィック容量を見積もることができます。MCU は専用 memcache の 10,000 MCU/秒/GB を予想できるように定義されます。Google Cloud Console にアプリで現在使用している MCU の量が表示されます。
MCU はおおよその統計見積もりであり、線形単位ではありません。値の読み取りまたは書き込みをする各キャッシュ オペレーションは、値のサイズに依存した対応する MCU コストがかかります。set
の MCU は値のサイズによって異なります。成功した get-hit
オペレーションのコストの 2 倍になります。
値アイテムサイズ(KB) | get-hit の MCU コスト |
set の MCU コスト |
---|---|---|
1 以下 | 1.0 | 2.0 |
2 | 1.3 | 2.6 |
10 | 1.7 | 3.4 |
100 | 5.0 | 10.0 |
512 | 20.0 | 40.0 |
1024 | 50.0 | 100.0 |
値を読み書きしないオペレーションには固定の MCU コストがかかります。
オペレーション | MCU |
---|---|
get-miss |
1.0 |
delete |
2.0 |
increment |
2.0 |
flush |
100.0 |
stats |
100.0 |
get-miss
オペレーションは指定したキーで値が保存されていないことを検出する get
です。
次のステップ
- memcache の使用で memcache の構成、モニタリング、使用方法を学習する。