MCPサーバーのキャッシュ:87回の障害を経て学んだこと
MCPサーバーにキャッシュは不要だと思っていました。
私のナレッジベースには数千件のエントリしかなく、クエリも高速でした。しかし、それは間違いでした。
87回の本番環境での障害と、タイムアウトのデバッグに費やした3日間を経て、私は手痛い教訓を得ました。すべてのMCPサーバーにはキャッシュが必要です。たとえ小規模なものであっても。
何が起きたのかを説明します。
サーバーはノートを見つけるためにセマンティック検索を使用していました。ほとんどの場合は正常に動作していましたが、ある時、問題が発生しました。
- リクエストの途中で接続が切断される。
- Claude Desktopが60秒後にタイムアウトする。
- Nginxが504 Gateway Timeoutを返す。
最悪な点は? それは、同じクエリを繰り返した時にだけ発生したことです。
ユーザーが同じ質問を2回行った際、AIが考えている間に接続がアイドル状態になることがあります。すると、プロキシが接続を切断します。Claudeは自動的にリクエストを再試行します。その結果、全く同じ検索が同時に2つ実行されることになります。
複数の再試行が発生すると、データベースのコネクションプールが枯渇します。そして、すべてが停止します。
AIの最終的な回答をキャッシュすべきではないと気づきました。それはMCPにとっては複雑すぎます。代わりに、負荷の高い部分、つまりセマンティック検索とコンテンツの取得をキャッシュする必要がありました。
私は2段階のキャッシュ戦略に移行しました。
• レベル1:頻繁なクエリ用のインメモリキャッシュ。これは極めて高速です。 • レベル2:再起動後もデータを共有するためのRedisキャッシュ。
また、これを機能させるために以下のルールに従いました。
- クエリの正規化:クエリを小文字に変換し、余分なスペースを削除します。これによりキャッシュヒット率が向上します。
- ストリームではなく結果をキャッシュする:検索結果のみをキャッシュします。検索処理が時間の95%を占めているからです。
- 段階的な機能縮退(Graceful degradation):Redisがダウンしても、サーバーは動作し続けます。単にデータベースに直接アクセスするだけです。キャッシュは最適化のためのものであり、リクエストを成功させるための必須条件ではありません。
結果は劇的でした。
平均検索時間は320msから12msになりました。これは27倍の高速化です。全体のキャッシュヒット率は73%に達しました。ほとんどのクエリはデータベースにすら到達しません。
もしMCPサーバーを構築するなら、次のようにしてください。
- 個人利用の場合:インメモリキャッシュを使用してください。ランダムなタイムアウトを防げます。
- 公開サービスの場合:Redisを用いた2段階のアプローチを採用してください。クラッシュを防ぎ、速度を向上させます。
キャッシュとは信頼性のためのものです。再試行と接続失敗の連鎖を断ち切ってくれます。
Optional learning community: https://t.me/GyaanSetuAi
