The Amazon Builder's Libraryを読む:『キャッシングの課題と戦略』

第4回のオンライン輪読会に備えて読んだ内容を自分なりにまとめておく。

今回の記事はこちら。

 

aws.amazon.com

  

 

[期待/予想する内容]

この記事の目次は次のとおりである。

  • 概要:エクスタシーとキャッシュの苦痛
  • キャッシングを使用する場合
  • ローカルキャッシュ
  • 外部キャッシュ
  • インラインキャッシュとサイドキャッシュ
  • キャッシュの有効期限
  • その他の考慮事項
  • Amazon のベストプラクティスと考慮事項

 

「概要:エクスタシーとキャッシュの苦痛」……キャッシュの苦痛。エクスタシーが何を意味するのかピンとこないが、苦痛は分かるような気がする。実際にキャッシュを実装しようとすると、話はそれほど簡単ではない。キャッシュに利用するメモリの運用だったり、キャッシュされたデータと元データの同期だったり、問題は山ほどある。

 

「キャッシングを使用する場合」……導入だろうか。キャッシュはいいぞ、みたいな一般論?

 

「ローカルキャッシュ」……おそらく、APサーバーやモバイルやPCのクライアントアプリケーションのメモリ上にキャッシュするタイプの話だろうか。

 

「外部キャッシュ」……RedisやMemcachedなどの有名どころのミドルウェアの話が来るはず。AWSでもこの2つはElastiCacheとしてサービス化されているし。あ、EhCacheなんてのもあったな。あれは最近も使われているんだろうか。

 

「インラインキャッシュとサイドキャッシュ」……これはよくわからない。どういうやつだろう。注意して読もう。

 

「キャッシュの有効期限」……有効期限マジ無理……難しすぎる。どうやって決めるんだろう?決める時のベストプラクティスとか書かれているだろうか。でもきっと、泥臭く計測すべしってことな気がする。

 

「その他の考慮事項」……ここも注意して読んだ方がいい気がする。外部キャッシュのミドルウェアの安定性とか、(輪読会第1回の『デプロイ時におけるロールバックの安全性の確保』で出てきたような)キャッシュのバージョニングの話だろうか。

 

Amazon のベストプラクティスと考慮事項」……前回の『運用の可視性を高めるために分散システムを装備する』同様、Amazonのベストプラクティスパートがあるのは嬉しい。おそらく、ここが一番読むに値する箇所だ。なんなら、時間のない人はここだけ読むといいんじゃないだろうか。

 

[記事の要約]

次に、実際に記事を読んだ内容を箇条書きでまとめる。

 

概要:エクスタシーとキャッシュの苦痛

  • 他サービスの呼び出しは遅く、他サービスのスケールアウトには費用がかかるという課題
  • キャッシュを導入し依存すると、他サービスのスケールが不要になり縮小されるが、一度問題が起きると自サービスと他サービスの両方が停止する可能性がある
  • キャッシュによってサービスの動作が変わる、災害に繋がる危険性

 

キャッシングを使用する場合

  • キャッシュを追加する前に依存サービスのレイテンシを調査
  • 特定のデータが頻繁に読まれる場合はキャッシュが有用である
  • リクエストごとにレスポンスが異なる場合はキャッシュは有用でない
  • データの一貫性、結果整合性を考慮すべし

 

ローカルキャッシュ

  • オンボックスキャッシュ:同一プロセスのメモリ上のキャッシュ
  • 運用オーバーヘッドがなく、既存サービスへの統合リスク低い
  • 欠点1:キャッシュデータの自サービスのフリート内での一貫性に欠ける
  • 欠点2:サーバーごとのキャッシュのため、自サービスがスケールすると依存する他サービスに影響する
  • 欠点3:コールドスタートの影響をうける

 

外部キャッシュ

  • RedisやMemcachedの外部フリートにキャッシュする
  • ローカルキャッシュの欠点を解消でき、より大きなストレージを利用できる
  • 欠点1:システム全体の複雑度と運用負荷の増加
  • 欠点2:キャッシュフリートのスケーリングの難しさ

 

インラインキャッシュとサイドキャッシュ

  • インラインキャッシュ:リードスルー/ライトスルーとも。DynamoDB AcceleratorやVarnishなど。APIがキャッシュとして機能する。
  • サイドキャッシュ:外部キャッシュとしてMemcached、Redis。ローカルキャッシュとして、EhCacheやGoogle Guavaなど。アプリケーションコードに実装が必要。
  • インラインキャッシュの利点:クライアントロジックの変更が不要
  • インラインキャッシュの欠点:透過的であるがゆえに可用性に直結

 

キャッシュの有効期限

  • キャッシュの難しいポイント:キャッシュサイズ、有効期限ポリシー(例:TTL)、削除ポリシー(例:LRU)
  • メトリクスを実測すべし:キャッシュのヒット/ミス、合計サイズ、依存サービスへのリクエスト数
  • 回復力向上のために:ソフトTTLとハードTTL
  • ソフトTTL:クライアントが認識する有効期限
  • ハードTTL:依存サービスが利用できない場合にキャッシュを利用できる有効期限

 

その他の考慮事項

  • 依存サービスのエラー時のキャッシュ動作の対応
  • パターン1:最後にキャッシュされたデータを利用する(ハードTTL
  • パターン2:エラーをキャッシュ(ネガティヴキャッシュ)
  • キャッシュのセキュリティを評価すべし:転送中および保管中のデータの暗号化、キャッシュポイズニング攻撃、サイドチャネルタイミング攻撃
  • thundering herd問題:稲妻の群問題。同時多発的に依存サービスにリクエストが飛んで高負荷となる
  • これはリクエストの合体で対応できる(Varnishなどに組み込まれている)

 

Amazon のベストプラクティスと考慮事項

  • キャッシュの正当な必要性確認:コスト、レイテンシ、可用性の観点から。
  • キャッシュのメトリクスを監視し、適切に調整する、運用を考慮する
  • 慎重にキャッシュサイズ、有効期限ポリシー、削除ポリシーを選択する
  • キャッシュ障害時の回復力を持たせる、負荷テストをする
  • セキュリティ面を考慮する
  • キャッシュのシリアル化ロジックに注意してバージョン番号を埋め込むなどする
  • エラー処理、ネガティヴキャッシュの検討

 

[予想のふりかえりなど]

キャッシュは分散してないシステム内で実装経験があるので、なんとなく有効期限とか削除ポリシーは馴染みがあった。

とはいえ、依存サービス関連での障害や、それに伴うエラー処理やネガティヴキャッシュなど、まだまだ自分に足りていなかったものを本稿を通じて得ることができた。

セキュリティのところで出てきたサイドチャネルタイミング攻撃は、2年くらい前に話題になったメルトダウンとかスペクターといったCPUの脆弱性を思い起こさせる。あれもキャッシュの一部だから、たしかに関係する話だ。セキュリティも、これまであまり考えられていなかったので、読んで新しい視点を得られて良かった。

ベストプラクティスは相変わらずとても勉強になる。

 

また、既に学習済みの他のAmazon Builders Libraryとの繋がりも見えてきて分かりやすかった。

 

[まとめ]

  • 「The Amazon Builder's Library」の『キャッシングの課題と戦略』を読んだ
  • キャッシュのセキュリティやエラーハンドリングなど、新しい視点を得ることができた
  • やはりメトリクス最強、丁寧に作っていく必要性を感じた

 

引き続きAmazon Builder's Library読んでいくぞ。