見出し画像

ElastiCasheのキャッシュ戦略 | DVA学習ログ [#AWSメモ]

Lazy Loading(遅延読み込み)

概要

  • 先にキャッシュからの読み込みを試みる

  • キャッシュヒットしなかった場合にDBから読み込み、結果をキャッシュに書き込む

遅延読み込みの説明(AWS BlackBelt資料より)

メリット

  • リクエストされたデータのみがキャッシュされるため、キャッシュ枯渇を回避できる

  • ノード障害に強い

    • キャッシュミスしたら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への書き込みに伴い、キャッシュへのデータ追加もしくはデータ更新を行う

書き込みスルーのパターン1(AWS BlackBelt資料より)
書き込みスルーのパターン2(AWS BlackBelt資料より)

メリット

  • キャッシュが常に最新に保たれる

  • データ更新のレイテンシは長くなるが、ユーザーはデータ読み取りのレイテンシより寛容なことが一般的である

    • 書き込みがキャッシュと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


いいなと思ったら応援しよう!

この記事が参加している募集