📑 この章の目次
title: キャッシュ・非同期処理 icon: ⚡ card_desc: 処理を速くする・後回しにする技術の使い分け — キャッシュ/無効化/TTL・非同期/キュー・同期との違い slug: 09-cache-async
09 キャッシュ・非同期処理 — 処理を速くする・後回しにする技術の使い分け
「ページの表示が遅い」「重い処理でユーザーを待たせている」——この2つの問題に、開発現場は決まって2つの技術で立ち向かいます。キャッシュ(結果を使い回して速くする)と非同期処理(重い処理を後回しにする)です。この章では、この2つの本質と使い分けを根本から理解します。
一言でいうと
キャッシュは、一度取得・計算した結果を使い回して速くする技術。非同期処理は、時間のかかる処理を後回しにしてユーザーを待たせない技術。この2つは「速くする」という目的で語られますが、根本的に別の仕組みです。キャッシュは「同じ計算を何度もしない」・非同期は「重い処理を待たせない」と、それぞれの得意な問題に使い分けます。
1. なぜキャッシュ・非同期処理が必要なのか
Webサービスにおいて、速さは機能と同じくらい重要です。
- ユーザーは数秒の待ちで離脱する(「3秒ルール」と呼ばれる目安がある)
- 検索順位(SEO)にも表示速度が影響する
- 重い処理を毎回同期的に行うと、1回のリクエストが遅く全体が詰まる
ここで問題になるのは、2種類の「遅さ」です:
| 遅さの種類 | 例 | 向く技術 |
|---|---|---|
| 同じ問い合わせを何度も繰り返す | 人気商品ページを毎回DBから組み立てる | キャッシュ(結果を使い回す) |
| 1回の処理そのものが重い | メール送信・画像変換・大量集計 | 非同期処理(後回しにする) |
キャッシュと非同期処理は、この**別々の「遅さ」**にそれぞれ効く技術です。
2. キャッシュとは —— 結果を使い回す
キャッシュ(cache/「隠し場所」由来)は、一度取得・計算した結果を一時保存しておき、次はそれを使い回す仕組みです。「同じ問いには同じ答え」を、毎回やり直さずに返せます。
どこに置くか
キャッシュは、本来のデータ源(データベース等)の手前に置きます:
ユーザー → [キャッシュ] → データベース
(あれば即返す) (なければ取りに行く・キャッシュにも保存)
- キャッシュにあればキャッシュヒット(即座に返す・速い)
- なければキャッシュミス(本来の源へ取りに行き・キャッシュにも保存)
💡 キャッシュの保管場所としては、Redis(→ 第7章)のようなキー・バリュー型 NoSQL や、アプリのメモリがよく使われます。静的ファイル(画像・CSS等)なら CDN(シーディーエヌ/Content Delivery Network)—— 世界中のサーバーにファイルを配置し、ユーザーに地理的に近い所から配信する仕組み —— が代表例です。
例えていうと: 冷蔵庫
毎回スーパー(データベース)に行かず、**冷蔵庫(キャッシュ)**に食材を保存しておいて使い回す。冷蔵庫にあれば早いが、在庫が古くなる問題(後述)もある。
3. 🔑 キャッシュの核心 —— 速さと新しさのトレードオフ
ここが本章の核心の1つ目です。キャッシュの最大の難しさは**「古くなる」**ことです。
古さ(一貫性)の問題
キャッシュは**「副本(コピー)」です。本体(データベース)が変わっても、キャッシュが古いままなら「更新したのに画面が変わらない」**事故が起きます。
- 価格を変更したのに、古い価格が表示される
- 在庫がなくなったのに、在庫ありと表示される
これを防ぐのが無効化(invalidation/「キャッシュを捨てる」)です。本体が変わった時にキャッシュも消し、次回は新しく取り直させます。
TTL —— 寿命を決める
毎回無効化を管理するのは複雑なので、TTL(ティーティーエル/Time To Live/「寿命」)を設定する方法がよく使われます。「このキャッシュは5分間有効」のように期限を決め、過ぎたら自動で捨てられます。新しさの保証は「TTLの時間分だけ遅れる」ことで緩和されます。
重要 キャッシュは「速さ」と「新しさ」のトレードオフです。速くすればするほど古いデータを見せるリスクが増え、新しさを厳密に保てばキャッシュの効果が薄れます。**「どのデータを・どの程度古くても許すか」**をデータごとに判断するのが設計の核心です。
💡 業界有名な格言: 「計算機科学の難問題は2つしかない。命名とキャッシュ無効化だ」。キャッシュ無効化の設計がいかに難しいかを示す冗談で、現場でも共感されて広く使われます。
4. 非同期処理とは —— 重い処理を後回しにする
非同期処理(asynchronous/通称 async/エイシンク)は、時間のかかる処理の完了を待たず、先へ進む方式です。「後でやる」仕組みで、ユーザーを待たせません。
同期 vs 非同期
- 同期(
sync/シンク): 処理が終わるのを待ってから次へ。結果は確実だが、重いと待たされる - 非同期(
async): 処理を依頼だけして先へ進む。結果は後で届く(または要らない)
例: ユーザー登録で「確認メールを送る」処理。
- 同期: メール送信が終わるまでユーザーを待たせる(送信に5秒かかれば5秒待たされる)
- 非同期: 「メール送信」を後回しにし、ユーザーには**即座に「登録完了」**を返す。メールはバックグラウンドで送られる
キューとワーカー
非同期処理は**「依頼を並べておいて、別の係が順に処理する」**仕組みで実現します:
アプリ → [キュー(依頼の列)] → ワーカー(処理係)→ 実行
(即座に依頼だけ置いて戻る) (順に取り出して実行)
- キュー(
queue/「列」): 依頼を順に並べておく場所 - ワーカー(
worker): キューから依頼を取り出して実際に処理する係
例えていうと: レストラン
注文をとったら伝票を厨房に回して、すぐ客席に戻る(非同期)。料理ができるまで客をカウンターで立たせ続けない(同期ならそうなる)。料理は厨房(ワーカー)が順に作る。
5. 🔑 キャッシュと非同期の使い分け
ここが本章の核心の2つ目です。この2つは「速くする」で語られますが、目的が違います。混同しないことが大切です:
| キャッシュ | 非同期処理 | |
|---|---|---|
| 目的 | 同じ計算を何度もしない | 重い処理を待たせない |
| 効く問題 | 同じ問い合わせが頻発する | 1回の処理そのものが重い |
| 例 | 人気商品ページの組み立て | メール送信・画像変換・集計 |
| 速さの正体 | 結果の使い回し | 処理の後回し |
| 主な落とし穴 | 古いデータ(一貫性) | エラーの握り潰し・順序 |
重要 「速くする=キャッシュ」ではありません。「同じ結果を何度も計算している」ならキャッシュ、「1回の処理がそもそも重い」なら非同期、と原因で選びます。両方組み合わせる(重い処理の結果をキャッシュする等)こともあります。
6. なぜ「キャッシュ・非同期」が開発の作法なのか
ここまでを読むと、パフォーマンス改善が「道具を知っているか」でなく**「遅さの原因を見極めて適切な技術を選べるか」**の問題だと分かります。
作法として位置づけられる理由
- パフォーマンスは機能要件: 「遅い」はバグと同じ。速さを設計に組み込むのがプロの態度
- 原因別の引き出し: 遅さの原因(N+1・インデックス不足・キャッシュ不足・重い同期処理)ごとに、適切な手段を持つ
- トレードオフの理解: キャッシュは新しさ・非同期は即時性と、それぞれ代償を伴うことを知って使う
面接・実務での意味
「サービスが遅いと聞きました。どう調査し、どう改善しますか?」
この質問は、「パフォーマンス問題を論理的に切り分けられるか」を聞いています。「まず原因を特定する(DBは速いか・ネットワークは・計算量は)→ それに応じてインデックス・キャッシュ・非同期のいずれかを選ぶ」と原因から手段を逆算できる人が、現場で信頼されます。
7. よくある落とし穴と対処
| 落とし穴 | 何が起きるか | 正しい対応 |
|---|---|---|
| キャッシュの無効化忘れ | 古いデータが表示され続ける(一貫性崩壊) | 本体変更時に確実に無効化・TTLで寿命を設定 |
| キャッシュ雪崩(stampede) | TTL一斉切れで全キャッシュミス→DBに殺到 | 期限にばらつきを持たせる・再生成を1件に絞る |
| キャッシュしすぎ | メモリ枯渇・無駄な保存 | 本当に繰り返すものだけキャッシュする |
| 非同期のエラー握り潰し | 失敗に気づかず、依頼が「消えた」ように見える | 失敗をログ・リトライで確実に扱う(→ 第8章) |
| 非同期の順序依存を見落とす | 「Aの後にB」が必要なのに順不同で壊れる | 順序が重要なら同期にする・キューで順を保証 |
| 非同期=魔法と思い込む | 結局処理は遅いまま(後回しにしただけ) | 非同期は待たせないだけで、処理自体の重さは解決しない |
💡 キャッシュ雪崩(スタンピード/cache stampede): 多くのキャッシュが同時にTTL切れすると、一気に全リクエストがキャッシュミスになり、本来のデータ源(DB等)に殺到してダウンさせる事故。TTLに多少のランダムさを持たせる等で防ぎます。
まとめ
- 遅さには2種類: 同じ問いの反復(→キャッシュ)・1回の処理が重い(→非同期)
- キャッシュは結果を使い回して速くする。最大の難問は**「古さ(一貫性)」**・無効化・TTLで管理
- 非同期処理は重い処理を後回しにしユーザーを待たせない。キュー+ワーカーで実現
- 「速くする=キャッシュ」でなく、原因で選ぶ(使い回し vs 後回し)・両方組み合わせも
- パフォーマンス改善は原因を見極めて適切な技術を選べるかが問われる・トレードオフ(新しさ・即時性)を理解して使う
💡 次のステップ: 処理を「速くする・後回しにする」技術が見えました。次は、ソフトウェアの**「バージョン」**の話です。第10章では、「1.2.3」のような番号の意味と、依存ライブラリの管理(パッケージ管理)の作法を扱います。