キャッシュを学び直してみる
キャッシュについて学び直す
普段、なんとなく使用しているキャッシュについて、なぜキャッシュをするのか、キャッシュを使う時のメリデメはなんなのかなどをまとめました。
本記事に書かれていることは、各種参考にした記事等に詳細が載っていますので、参照してください。
記事のゴール
- この記事を読んだ人が、キャッシュとは何かを説明できるようになる
- どのようなレイヤーでキャッシュが用いられるのかをイメージできるようになる
- キャッシュを使用する時には、適切な運用が必要であることをなんとなくイメージできるようになる
キャッシュとは
データの一部を一時的に保存しておき、再度同じデータにアクセスする時に、実際に保存されている場所に問い合わせするよりも早くデータを取得できるようにしておくこと
データの一部を保存しておき、使いまわせるようにしておけば、どんなレイヤーで使われてもそれば「キャッシュ」と呼ぶことができると思います。
Redis やMemcached はキャッシュの役割を担うことが多いが、これはキャッシュ戦略の一部であり、「キャッシュ」自体を指しているわけではありません。
適用先
データを使いまわすために一時的に保存する必要があり、かつそれを利用するような箇所のレイヤーに適用できます。
- オペレーティングシステム
- コンテンツ配信ネットワーク(CDN)
- DNS
- webアプリケーション
- データベース
キャッシュをするデータ
レイヤーとは別に、どのようなデータがキャッシュする対象になるかの例を挙げておきます。
- データベースクエリの結果
- 計算量の多い計算
- APIリクエスト/応答
- HTML
- JavaScript
- 画像ファイル
そのほかにも色々...。
キャッシュのメリット
低速なストレージにアクセスする必要を減らすことによって、データ取得のパフォーマンスを向上させることがキャッシュのメリットで、これを正しく享受できるようにキャッシュを運用する必要があります。
各種レイヤーで使用した時のメリットを簡単に紹介します。
- アプリケーションのパフォーマンス向上
- データベースのコスト削減
- 予測可能なパフォーマンス
- 外部サービスからデータを取得する場合、負荷状況など色々な要因でパフォーマンスが予測できない
- インメモリキャッシュを利用することでパフォーマンスが予測可能になる
- データベースのホットスポットを排除する
- 多くのデータの中でも、アクセスされる頻度は変わる。有名人のデータや、人気の商品などは頻繁にアクセスされるため、データベースにホットスポットが発生する可能性がある
- ホットスポットが発生することで、データベースリソースを超過し、オーバープロビジョニング領域まで使用する場合も起こり得る
- インメモリキャッシュにアクセス頻度が高いデータを保存しておくことで、ホットスポットが発生する可能性を提言できる
- 読み取りスループット(IOPS)の増加
- 外部サービスにアクセスせず、インメモリで済ませられるため、レイテンシーが短くなる
キャッシュのデメリット
大きなメリットを享受できるキャッシュですが、for文を1つ増やすのとは違い、システムの運用物が増えることになるため、正しく運用しなければなりません。
- 適切な管理をする必要がある
- キャッシュはあくまで一時的な保存を行うことなので、消えることが前提である
- 分散型システムでの運用を前提とする場合、キャッシュの更新タイミングを気にしなければならない
- 高速化を行うことができるが、不用意に適用すると根本的な問題を置き去りにしてしまう可能性がある
キャッシュに適するデータの性質
メリットとデメリットをならべましたが、要するに正しく運用でき、本当に必要な時にキャッシュを利用する必要がある。ということです。
キャッシュに適したデータの性質を並べます。
- 削除が許容されること
- 読み込み頻度が高いこと
- 書き込み頻度が低いこと
キャッシュ戦略
繰り返しになりますが、キャッシュを行うことで上記のメリットを享受することができる一方で、適切に使うことが求められます。
得られるメリットの捉え方を間違えると、間違った使い方をしてしまう場合もあります。
例えば、遅いクエリの結果をキャッシュすれば素早いレスポンスを実現できるが、遅いクエリはそのままであるため、根本的な解決はできていない。などです。
キャッシュを導入すると戦うことになる問題に関しては下記を参照してください。
Webアプリケーションのキャッシュ戦略とそのパターン
キャッシュの概要 では、ベストプラクティスとして下記のように記載されています。
キャッシュをして一時的に保存するデータには有効期限などを設け、正しく運用できるようにすることが求められます。
重要なこと
データの有効性を把握することが重要。TTL(有効期限)などのコントロールを適用して、必要に応じてデータの有効期限が切れるように設定できる
キャッシュ環境に高可用性が必要であれば、Redis
などのインメモリエンジンを使用できる。
インメモリレイヤーを独立したデータストレージとして使用できる
インメモリエンジンないに存在するデータに対して、適切なRTO/RPOを定義することが重要
様々なインメモリエンジンの設計戦略と機能を適用して、要件を満たすことができる
アーキテクチャパターン
上記のような注意事項に対して、キャッシュを正しく運用できるように、いくつかのパターンが存在しています。
-
Cache-Aside Pattern
シンプルなアーキテクチャ
キャッシュサーバーを用意して、アプリケーションサーバーに適宜問い合わせをします。
集中型のキャッシュサーバーを用意するにあたってキャッシュを保持するタイミングが異なる2つのパターンがあります。- read-aside-pattern
データを読み込んだ時にキャッシュとして保存する - write-aside-pattern
書き込みを行った時にキャッシュを行う
- read-aside-pattern
-
Broker Pattern
キャッシュにあったらキャッシュから返す。
なかったら1時ストレージに問い合わせ、その結果を返しつつキャッシュに入れる。という形をとっています。
メリット- アクセス頻度が高いデータがキャッシュに保存される
デメリット - 最初の取得が重い
- キャッシュが蓄えられていない場合に、全て1次ストレージに向く
- アクセス頻度が高いデータがキャッシュに保存される
-
多層キャッシュ
- local とremote でそれぞれキャッシュを行う
- local キャッシュが亡くなった際に、remote キャッシュに問い合わせることで、オリジンに対するリクエスト量を減らす
- 詳しくは下記を参照してください
どんな種類のキャッシュがあるか
キャッシュの要件を満たしていれば、どのレイヤーでも適用することができます。
下記はその例です
キャッシュによく使用される技術
キャッシュのアーキテクチャで紹介したように、ローカルメモリでのキャッシュよりも、分散型システム環境下で用いられることを前提として、
アプリケーション側でClient Library を利用し、TCP/IP を通してCacheServer にリクエストする、client/serverモデルで運用される技術がよく使われます。
最後に、キャッシュサーバーとしてよく用いられる2つの技術を簡単に紹介します。
また、この2つはよく比較される技術でもあり、詳細な比較はいろんな方が記事を上げてくれていますので、 どちらが自分が使用するべきかは別の記事を参考にしてください。
Redis(REmote DIctionary Server)
- データの一貫性に重点を置いている
- シングルスレッド動作
- Server/Client モデルを採用していることから、リクエストの捌き方を決める必要がある
- リクエストの捌きかたがシングルスレッド
- マルチスレッドよりも完結なため、こちらを採用している
Memcached(memory cache daemon)
読み方は「メムキャッシュディー」
- シンプルさとスピードに重点を置いている
- マルチスレッド動作
- kvs(Key Value Store)型のデータ保存手法を採用している
C10K 問題
クライアントが約1万台に達すると、Webサーバーの性能に余裕があるにも関わらず、レスポンス性能が大きく下がる問題です。
クライアント1つ1つにプロセスを生成する仕様の場合、OSの最大プロセス数を使い果たしてしますことが原因の一つです。
Nginx Redis,Memcached ではC10K 問題が怒らないようにイベントループを回しています。
関連ワード
- 分散システム
- データベース
参考文献
【図解】キャッシュ戦略って何?キャッシュを使ったクエリチューニングって何?
Webアプリケーションにおける正しいキャッシュ戦略
Discussion