

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# キャッシュを使用してデータベースの需要を減らす
<a name="net-caching"></a>

## 概要:
<a name="net-caching-overview"></a>

キャッシュを効果的な戦略として使用し、.NET アプリケーションのコストを削減できます。アプリケーションがデータへの頻繁なアクセスを必要とする場合、多くのアプリケーションは、SQL Server などのバックエンドデータベースを使用します。需要に対応するためにこれらのバックエンドサービスを維持するコストは高くなる可能性がありますが、効果的なキャッシュ戦略を使用して、サイジングとスケーリングの要件を減らすことでバックエンドデータベースの負荷を軽減できます。これにより、コストを削減し、アプリケーションのパフォーマンスを向上させることができます。

キャッシュは、SQL Server などのより高価なリソースを使用する読み込み負荷の高いワークロードに関連するコストを節約するのに役立つ手法です。ワークロードに適した手法を使用することが重要です。例えば、ローカルキャッシュはスケーラブルではなく、アプリケーションのインスタンスごとにローカルキャッシュを維持する必要があります。基盤となるデータソースのコストが低いほどキャッシュメカニズムに関連する追加コストが相殺されるように、パフォーマンスへの影響を潜在的なコストと比較検討する必要があります。

## コストへの影響
<a name="cost-impact"></a>

SQL Server では、データベースのサイズ設定時に読み取りリクエストを考慮する必要があります。これは、負荷に対応するためにリードレプリカを導入する必要がある場合があるため、コストに影響する可能性があります。リードレプリカを使用する場合は、SQL Server Enterprise Edition でのみ使用できることを理解することが重要です。このエディションには、SQL Server Standard Edition よりも高価なライセンスが必要です。

次の図は、キャッシュの有効性を理解するのに役立つように設計されています。SQL Server Enterprise Edition を実行している 4 つの db.m4.2xlarge ノードを持つ Amazon RDS for SQL Server を示しています。これは、1 つのリードレプリカを持つマルチ AZ 設定でデプロイされます。排他的な読み取りトラフィック (SELECT クエリなど) は、リードレプリカに送信されます。これに対して、Amazon DynamoDB は r4.2xlarge の 2 ノード DynamoDB Accelerator (DAX) クラスターを使用します。

次のグラフは、多くの読み取りトラフィックを処理する専用リードレプリカの必要性をなくした結果を示しています。



![\[専用リードレプリカを取り除いた結果を示すグラフ\]](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/optimize-costs-microsoft-workloads/images/graph_rds_dax.png)


リードレプリカなしでローカルキャッシュを使用するか、Amazon RDS 上の SQL Server と並行して DAX をキャッシュレイヤーとして導入することで、大幅なコスト削減を実現できます。このレイヤーは SQL Server から負荷を軽減し、データベースの実行に必要な SQL Server のサイズを縮小します。

## コスト最適化の推奨事項
<a name="net-caching-rec"></a>

### ローカルキャッシュ
<a name="net-caching-rec-local-caching"></a>

ローカルキャッシュは、オンプレミス環境またはクラウドでホストされているアプリケーションのコンテンツをキャッシュするために最も一般的に使用される方法の 1 つです。これは、実装が比較的簡単で直感的であるためです。ローカルキャッシュには、データベースまたは他のソースからコンテンツを取得し、より迅速にアクセスできるようにメモリまたはディスクでローカルにキャッシュすることが含まれます。このアプローチは実装は簡単ですが、一部のユースケースには適していません。例えば、これには、アプリケーションの状態やユーザーの状態を保持するなど、キャッシュコンテンツを経時的に保持する必要がある場合のユースケースが含まれます。もう 1 つのユースケースは、キャッシュされたコンテンツに他のアプリケーションインスタンスからアクセスする必要がある場合です。

次の図は、4 つのノードと 2 つのリードレプリカを持つ高い可用性の SQL Server クラスターを示しています。



![\[4 つのノードと 2 つのリードレプリカを持つ高い可用性の SQL Server クラスター\]](http://docs.aws.amazon.com/ja_jp/prescriptive-guidance/latest/optimize-costs-microsoft-workloads/images/dax_cluster.png)


ローカルキャッシュでは、複数の EC2 インスタンス間でトラフィックの負荷分散が必要になる場合があります。各インスタンスは、独自のローカルキャッシュを維持する必要があります。キャッシュがステートフル情報を保存する場合、データベースへの定期的なコミットが必要であり、ユーザーは後続のリクエスト (スティッキーセッション) ごとに同じインスタンスに転送される必要がある場合があります。これは、アプリケーションのスケーリングを試みる際に課題となります。トラフィックの不均等な分散により、一部のインスタンスが過剰に利用される一方で、一部のインスタンスは十分に利用されない可能性があるためです。

.NET アプリケーションには、インメモリまたはローカルストレージ使用のいずれかでローカルキャッシュを使用できます。そのためには、ディスクにオブジェクトを保存して必要に応じて取得するか、データベースからデータをクエリしてメモリに保持する機能を追加できます。例えば、C\$1 で SQL Server からのデータの、メモリおよびローカルストレージでのローカルキャッシュを実行するには、`MemoryCache` ライブラリと `LiteDB` ライブラリの組み合わせを使用できます。`MemoryCache` はインメモリキャッシュを提供し、`LiteDB` は高速で軽量な NoSQL ディスクベースの埋め込みデータベースです。

インメモリキャッシュを実行するには、.NET ライブラリ `System.Runtime.MemoryCache` を使用します。次のコード例は、`System.Runtime.Caching.MemoryCache` クラスを使用して、メモリ内にデータをキャッシュする方法を示しています。このクラスは、アプリケーションのメモリにデータを一時的に保存する方法を提供します。これにより、データベースや API など、より高価なリソースからデータを取得する必要がなくなり、アプリケーションのパフォーマンスを向上させることができます。

コードの仕組みは次のとおりです。

1. `_memoryCache` という名前の `MemoryCache` のプライベート静的インスタンスが作成されます。キャッシュには、識別するための名前 (`dataCache`) が付けられます。そして、キャッシュがデータを保存して取得します。

1. `GetData` メソッドは、`string` キーと、`getData` という `Func<T>` デリゲートの 2 つの引数を取るジェネリックメソッドです。キーは、キャッシュされたデータを識別するために使用され、`getData` デリゲートは、データがキャッシュに存在しない場合に実行されるデータ取得ロジックを表します。

1. メソッドはまず、`_memoryCache.Contains(key)` メソッドを使用してキャッシュにデータが存在するかどうかを確認します。データがキャッシュにある場合、メソッドは `_memoryCache.Get(key)` を使用してデータを取得し、期待されるタイプ T にキャストします。

1. データがキャッシュにない場合、メソッドは `getData` デリゲートを呼び出してデータを取得します。そして、`_memoryCache.Add(key, data, DateTimeOffset.Now.AddMinutes(10))` を使用してキャッシュにデータを追加します。この呼び出しは、キャッシュエントリが 10 分後に期限切れになることを指定し、その時点でデータは自動的にキャッシュから削除されます。

1. `ClearCache` メソッドは `string` キーを引数として受け取り、`_memoryCache.Remove(key)` を使用して、そのキーに関連付けられたデータをキャッシュから削除します。

```
using System;
using System.Runtime.Caching;

public class InMemoryCache
{
    private static MemoryCache _memoryCache = new MemoryCache("dataCache");

    public static T GetData<T>(string key, Func<T> getData)
    {
        if (_memoryCache.Contains(key))
        {
            return (T)_memoryCache.Get(key);
        }

        T data = getData();
        _memoryCache.Add(key, data, DateTimeOffset.Now.AddMinutes(10));

        return data;
    }

    public static void ClearCache(string key)
    {
        _memoryCache.Remove(key);
    }
}
```

次のコードを使用できます。

```
public class Program
{
    public static void Main()
    {
        string cacheKey = "sample_data";

        Func<string> getSampleData = () =>
        {
            // Replace this with your data retrieval logic
            return "Sample data";
        };

        string data = InMemoryCache.GetData(cacheKey, getSampleData);
        Console.WriteLine("Data: " + data);
    }
}
```

次の例は、[LiteDB](https://www.litedb.org/) を使用してローカルストレージにデータをキャッシュする方法を示しています。LiteDB は、インメモリキャッシュの代替または補完として使用できます。次のコードは、LiteDB ライブラリを使用してローカルストレージにデータをキャッシュする方法を示しています。`LocalStorageCache` クラスには、キャッシュを管理するための主要な関数が含まれています。

```
using System;
using LiteDB;

public class LocalStorageCache
{
    private static string _liteDbPath = @"Filename=LocalCache.db";

    public static T GetData<T>(string key, Func<T> getData)
    {
        using (var db = new LiteDatabase(_liteDbPath))
        {
            var collection = db.GetCollection<T>("cache");
            var item = collection.FindOne(Query.EQ("_id", key));

            if (item != null)
            {
                return item;
            }
        }

        T data = getData();

        using (var db = new LiteDatabase(_liteDbPath))
        {
            var collection = db.GetCollection<T>("cache");
            collection.Upsert(new BsonValue(key), data);
        }

        return data;
    }

    public static void ClearCache(string key)
    {
        using (var db = new LiteDatabase(_liteDbPath))
        {
            var collection = db.GetCollection("cache");
            collection.Delete(key);
        }
    }
}

public class Program
{
    public static void Main()
    {
        string cacheKey = "sample_data";

        Func<string> getSampleData = () =>
        {
            // Replace this with your data retrieval logic
            return "Sample data";
        };

        string data = LocalStorageCache.GetData(cacheKey, getSampleData);
        Console.WriteLine("Data: " + data);
    }
}
```

頻繁に変更されない静的キャッシュまたは静的ファイルがある場合は、これらのファイルを Amazon Simple Storage Service (Amazon S3) オブジェクトストレージに保存することもできます。アプリケーションは、起動時に静的キャッシュファイルを取得してローカルで使用できます。.NET を使用して Amazon S3 からファイルを取得する方法の詳細については、Amazon S3 ドキュメントの「[オブジェクトのダウンロード](https://docs.aws.amazon.com/AmazonS3/latest/userguide/download-objects.html)」を参照してください。

### DAX を使用したキャッシュ
<a name="net-caching-rec-caching-dax"></a>

すべてのアプリケーションインスタンスで共有できるキャッシュレイヤーを使用できます。[DynamoDB Accelerator (DAX)](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DAX.concepts.html) は、DynamoDB 用のフルマネージドで可用性の高いインメモリキャッシュで、10 倍のパフォーマンス向上を実現できます。DAX を使用すると、DynamoDB テーブルで読み取りキャパシティユニットを過剰にプロビジョニングする必要性を減らすことでコストを削減できます。これは、読み取り負荷が高く、個々のキーに対して繰り返し読み取りが必要なワークロードに特に役立ちます。

DynamoDB は、オンデマンドで、またはプロビジョニングされたキャパシティに基づいて料金が決まるため、1 か月あたりの読み取りと書き込みの回数がコストに影響します。読み取り負荷の高いワークロードがある場合、DAX クラスターは、DynamoDB テーブルの読み取り回数を減らすことでコストを削減できます。DAX を設定する方法については、DynamoDB ドキュメントの「[DynamoDB Accelerator (DAX) とインメモリアクセラレーション](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DAX.html)」を参照してください。.NET アプリケーション統合の詳細については、YouTube の「[Integrating Amazon DynamoDB DAX into Your ASP.NET Application](https://www.youtube.com/watch?v=ZMkLhD8OxYQ)」をご覧ください。

## その他のリソース
<a name="net-caching-resources"></a>
+ 「[DynamoDB Accelerator (DAX) とインメモリアクセラレーション - Amazon DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/DAX.html)」(DynamoDB ドキュメント)
+ 「[Integrating Amazon DynamoDB DAX into Your ASP.NET Application](https://www.youtube.com/watch?v=ZMkLhD8OxYQ)」(YouTube)
+ 「[オブジェクトのダウンロード](https://docs.aws.amazon.com/AmazonS3/latest/userguide/download-objects.html)」(Amazon S3 ドキュメント)