概要
モダンなウェブアプリケーションを開発していくにあたり、サービスのパフォーマンスを向上したいと思うケースってよくありますよね。
きっとその際に、インメモリデータストアとキャッシュ技術を利用し高速なパフォーマンスを実現することも解決策の1つになると思います。
Memcached や Redis、AWSを利用していればそれらソフトウェアの互換性のあるフルマネージドサービス Amazon ElastiCacheなどを利用しているんじゃないでしょうか。
今回は、そんなキャッシュ技術について、そもそもキャッシュってなんだっけを改めて振り返る記事となっております。
概要
キャッシュは、さまざまなレイヤーに存在します。
例えば、
- プロセッサコア(L1、L2、L3)内にハードウェアキャッシュ
- OS のページ/ディスクキャッシュ
- よく知られる、MemCached、Redis、または DynamoDB の DAX などのデータベースのキャッシュ
- APIキャッシュ
- CDN のエッジレベルでのキャッシュなどのL7階層(アプリケーション層)の HTTP キャッシュ
- DNSキャッシュ
- ブラウザでのキャッシュ
つまり、キャッシュは、さまざまな技術に採用されており、使用しております。
さて、キャッシュとはなんなのでしょうか?
キャッシュは、データのサブセットを一時的に保存するための高速なインメモリデータストレージ層です。キャッシュは元のデータソース(例えば、データベースなど)よりも読み取り時に高速であるため、データソースから直接データを取得するのではなく、キャッシュ内のデータにアクセスすることで、それ以降同じデータを読み取った際のデータの取得を高速化します。
また、キャッシュにより、データを計算するための複雑な操作やリソースを大量に消費する操作が回避され(例えば、ある読み取りに関してデータベースで複雑なSQLを発行しなければいけない場合など)、データの取得が効率化されます。
よくあるキャッシュのパターンで Read-Through と呼ばれるものがあります。
これは、アプリケーションがデータを必要とするとき、まずそれがキャッシュに存在するかどうかを確認します。
存在する場合、データはキャッシュから直接読み取られます。
データがキャッシュにない場合は、プライマリデータストアから読み取られるか、サービスによっては生成されます。データが読み取られるとキャッシュに保存されるため、それ以降のリクエストのためにキャッシュからデータを読み取れるようにできます。
①: キャッシュヒット
キャッシュがインメモリデータストア内にある場合、データストアから読み取る
②-データベースから読み取る
キャッシュ内に、データがなく読み取りに失敗した場合に、データベースから読み取り、インメモリデータストアに保存する
なぜキャッシュが必要なのか
なぜ、キャッシュが必要なのかの理由は、2つあります。
-
1つ目の理由は、読み取りたいデータを例えば、複雑なSQLクエリを利用しなければいけない場合に、データを読み取るだけで、多くのリソースを消費してしまいます。ただ、一度例えばクエリなどを発行し、そのデータを一定期間だけ保存することができれば、無駄なリソース消費がなくなるというわけです。
-
2つ目の理由は、データの取得を高速にすることです。キャッシュは元のデータソースからの読み込みよりも高速であり、キャッシュされた情報を迅速に取得できるため、ユーザーへのレスポンスも早くなるということですね。
キャッシュの例
ある Web ページがあり、そのサードバーにユーザに提供しているコンテンツに関連のあるものを表示する機能があったとします。
この関連するコンテンツというのは、プライマリのデータベース内にある大量のデータを処理することで機械学習用のアルゴリズムによって計算され、コンテンツが生成されます。
これは複雑な処理で、大量のコンピューターリソースが消費されます。
なお、上記の処理についてはユーザごとに計算する必要があり、同じデータを何度も計算するのに、時間もコンピュータリソースも大量に消費します。
影響範囲
- バックエンドとバックエンド用のデータベースに対して負荷がかかり、全体としてのインフラコストが増加しています。
- 関連するコンテンツの生成に時間がかかり、ユーザへのレスポンスに遅延が発生しています。
解決策
- これらの影響範囲が出るような問題を対処するときに「キャッシュ」が利用できます。
- キャッシュを利用することで、一度生成された関連コンテンツを一度計算された後にキャッシュに保存しておけば、次回以降、データを要求されたときは、コストのかかる処理を毎度毎度行うのではなく、キャッシュからのレスポンスを返すようにすることができます。
キャッシュの難しいところ
キャッシュがコストを節約し、重いワークロードをスケールし、レイテンシを短縮するなど、キャッシュがいかに便利であるかについてをこれまでは話してきました。
ただ、キャッシュはいい面だけがあるように見えて、トレードオフもあることを忘れてはいけません。
実は、キャッシュで難しいことは、キャッシュを使用したくない時の無効化とキャッシュの名前付けにあります。
キャッシュを使用したくない時の無効化
キャッシュを使用したくない時の無効化というのは、キャッシュ内のデータを無効としてマークするか、削除する処理のことを指しています。リクエストを受け取ったタイミングで、対応するデータを無効としたい場合に、その処理をどうするのか。例えば、対応する無効なデータをキャッシュミスとして処理し、元のデータソース(データベースまたはサービス) から強制的に新たなデータを生成するなどの処理をするという感じです。
それってどんな時??
例えば、元のデータソース(信頼できる情報源)内のデータが変更され、無効なデータがキャッシュに残ったときに発生します。
データのキャッシュが無効化されていない場合、一貫性のない情報、競合する情報、または不正確な情報をユーザに送ってしまう可能性があるということですね。
キャッシュ戦略
なので、こんな課題があった時にキャッシュを構成してアクセスするには、さまざまな方法があります。
次回の記事で、このキャッシュの戦略についてお話ししていこうと思います。
参考文献
コメント