
ElastiCasheのキャッシュ戦略 | DVA学習ログ [#AWSメモ]
Lazy Loading(遅延読み込み)
概要
先にキャッシュからの読み込みを試みる
キャッシュヒットしなかった場合にDBから読み込み、結果をキャッシュに書き込む

メリット
リクエストされたデータのみがキャッシュされるため、キャッシュ枯渇を回避できる
ノード障害に強い
キャッシュミスしたらDBから読み込み、キャッシュに格納するため
レイテンシが長くなるが機能する
デメリット
データ取得の遅延
キャッシュミス➝データベースへのクエリ➝キャッシュ書き込みの3ステップとなるため
古いデータを参照する可能性がある
キャッシュミス時のみキャッシュが最新化されるため
書き込みスルー戦略または追加TTL戦略で対応可能(後述)
実装コード例(AWS 公式ドキュメントのサンプルを一部改変)
get_customer(customer_id)
// キャッシュからの取得を試みる
customer_record = cache.get(customer_id)
if (customer_record == null)
// キャッシュミスならDBから取得し、キャッシュに書き込む
customer_record = db.query("SELECT * FROM Customers WHERE id = {0}", customer_id)
cache.set(customer_id, customer_record)
return customer_record
Write Through(書き込みスルー)
概要
DBへの書き込みに伴い、キャッシュへのデータ追加もしくはデータ更新を行う


メリット
キャッシュが常に最新に保たれる
データ更新のレイテンシは長くなるが、ユーザーはデータ読み取りのレイテンシより寛容なことが一般的である
書き込みがキャッシュとDB両方に発生するため
データ更新はある程度時間がかかることが一般的
デメリット
ノード障害やスケールアウトによって新規ノードが作成された際にデータの欠落が起こる
データベースのデータ追加や更新がないとキャッシュに書き込まれないため
遅延読み込みを書き込みスルーで指定すると軽減できる
読み込みもレイテンシが長くなるのでは?
利用されないキャッシュが増加する
TTLを追加することで軽減できる
実装コード例(AWS 公式ドキュメントのサンプルを一部改変)
save_customer(customer_id, values)
// DB更新後にキャッシュに書き込む
customer_record = db.query("UPDATE Customers WHERE id = {0}", customer_id, values)
cache.set(customer_id, customer_record)
return success
Adding TTL(追加TTL)
書き込んだキャッシュにTTL(有効期限)を設けることで、下記戦略それぞれのデメリットを軽減する
Lazy Loading:古いデータを参照する
Write Through:利用されないキャッシュの増加
古いデータを全く参照しなくなるわけではない
キャッシュ内のデータが古くなりすぎないようにして、キャッシュのデータを定期更新する
TTLの単位は下記
Memcached:秒単位
ValkeyまたはRedis OSS:ミリ秒単位
実装コード例(AWS 公式ドキュメントのサンプルを一部改変)
書き込み
save_customer(customer_id, values)
// Write Throughのキャッシュ書き込み時にTTLがついた形
customer_record = db.query("UPDATE Customers WHERE id = {0}", customer_id, values)
// 第3引数の「300」の箇所がTTL(ミリ秒または秒)の指定
cache.set(customer_id, customer_record, 300)
return success
読み込み
get_customer(customer_id)
// Lazy LoadingにTTLの分岐が追加された形
customer_record = cache.get(customer_id)
if (customer_record != null)
// キャッシュのTTLが指定範囲内であればリターンする
if (customer_record.TTL < 300)
return customer_record
customer_record = db.query("SELECT * FROM Customers WHERE id = {0}", customer_id)
// DBから読み込んでキャッシュに書き込む際に、TTLを指定して書き込む
cache.set(customer_id, customer_record, 300)
return customer_record
参考・引用資料
https://pages.awscloud.com/rs/112-TZM-766/images/AWS-Black-Belt_2023_Amazon-ElastiCache_0228_v1.pdf