ElastiCache の遅延読み込みと書き込みスルーの違い ── キャッシュミスのときだけデータベースから読む
記事の「実践」を 1 項目ずつ進めるためのページです。AWS マネジメントコンソールで操作したら、右の一覧にチェックを入れてください。チェックはこのブラウザに保存されます。
前提条件
- リージョン:
ap-northeast-1(東京) - 以下のリソースが作成済みであること
まだ用意していない場合は、「作り方の参考」の記事の手順で作れます。リソース名は、この記事の名前に読み替えてください。
| リソース種別 | リソース名 | 内容 | 作り方の参考 |
|---|---|---|---|
| VPC・サブネット | dva-cache-vpc | パブリックサブネット 2 つ(1a / 1c) | ― |
| ElastiCache クラスター | dva-cache-lab | Memcached、cache.t4g.micro × 1 ノード。SG で dva-cache-app-sg からの 11211 番ポートを許可 | Amazon ElastiCache でキャッシュを置いて読み込みを速くする(※この記事は Memcached を使う) |
| DynamoDB テーブル | dva-cache-records | パーティションキー record_id。rec-001〜rec-003 の 3 件(details に品名と値段) | Amazon DynamoDB でテーブルを作り Lambda から読み書きする |
| EC2 インスタンス | dva-cache-app | Amazon Linux 2023。Session Manager で接続でき、/opt/cache-lab/ に下の 3 つのスクリプトと、キャッシュとテーブルへの接続を設定した common.py がある | Amazon EC2 でインスタンスを起動しSSH接続する |
| スクリプト | 処理 |
|---|---|
lazy_get.py <キー> | 遅延読み込み。キャッシュを読み、無ければ DynamoDB から読んで TTL 300 秒でキャッシュに書く。HIT / MISS と処理時間を表示する |
update_db.py <キー> <値> | DynamoDB だけを更新する(キャッシュは触らない) |
write_through.py <キー> <値> | 書き込みスルー。DynamoDB を更新し、キャッシュも同じ値で更新する |
作成するリソース一覧
この実践では新しいリソースは作りません(キャッシュとテーブルの中身を読み書きします)。
手順 1: キャッシュクラスターを確かめる
AWS マネジメントコンソールにログインし、リージョンが ap-northeast-1(東京)であることを確認します。上部の検索バーに ElastiCache と入力し、「ElastiCache」を選択します。左側ナビゲーションの「Memcached キャッシュ」で dva-cache-lab を開き、ステータスが「Available」、エンジンが Memcached であることと、設定エンドポイント(dva-cache-lab.xxxxxx.cfg.apne1.cache.amazonaws.com:11211 の形)を確認します。スクリプトは、このクラスターのノードのエンドポイント(.0001. が入った名前)に接続するよう common.py に設定してあります。
手順 2: 遅延読み込みでキャッシュミスとヒットを見る
EC2 のコンソールで dva-cache-app を選択し、「接続」→「Session Manager」タブ →「接続」をクリックします。開いたターミナルで、次のコマンドを実行します。
cd /opt/cache-lab
export PYTHONWARNINGS=ignore
python3 lazy_get.py rec-001
python3 lazy_get.py rec-001
python3 lazy_get.py rec-001
export PYTHONWARNINGS=ignore は、Amazon Linux 2023 の Python 3.9 に対して boto3 が出すサポート終了の警告を表示しないためのものです(動作には影響しません)。
1 回目は MISS rec-001 -> banana: 100 yen (38.5 ms) ※データベースから読んでキャッシュに書いた、2 回目以降は HIT rec-001 -> banana: 100 yen (1.4 ms) のように表示されます(ミリ秒の値は実行のたびに変わります)。HIT のときはデータベースを読まないので、処理時間も短くなります。1 回目から HIT になった場合は、以前の実行の値がキャッシュに残っています。TTL の 300 秒が過ぎると MISS から始まります。
手順 3: データベースだけを更新して、古い値が返ることを見る
ほかのアプリケーションがデータベースの値段を変えた場面を再現します。
python3 update_db.py rec-001 "banana: 120 yen"
python3 lazy_get.py rec-001
データベースは banana: 120 yen に変わったのに、lazy_get.py は HIT rec-001 -> banana: 100 yen と古い値を返します。遅延読み込みでは、キャッシュに値が残っている間(TTL の 300 秒が過ぎるまで)、データベースの変更が反映されません。
手順 4: 書き込みスルーで更新する
書き込みスルーで、データベースとキャッシュを一緒に更新します。
python3 write_through.py rec-001 "banana: 130 yen"
python3 lazy_get.py rec-001
今度は HIT rec-001 -> banana: 130 yen と、新しい値がキャッシュから返ります。書き込みのたびにキャッシュも更新したので、古い値が残りません。
手順 5: キャッシュのメトリクスを見る
ElastiCache のコンソールで dva-cache-lab を開き、「メトリクス」タブを選択します。メトリクスは数十個あるので、検索欄に Get と入力して絞り込みます。「Get ヒット」(GetHits、キャッシュヒットの数)と「Get ミス」(GetMisses、キャッシュミスの数)のグラフに、ここまでの操作が反映されています(グラフに点が出るまで数分かかります)。ヒットの割合が高いほど、キャッシュがデータベースの読み込みを肩代わりできています。