【初心者向け】爆速アプリ開発の鍵!Azure Redis Cache徹底入門
はじめに:なぜアプリケーションは遅くなるのか?そしてその解決策としてのキャッシュ
Webアプリケーションやモバイルアプリケーションを開発する際、避けて通れない課題の一つに「パフォーマンス」があります。特に、ユーザー数が増加したり、扱うデータ量が膨大になったりすると、アプリケーションの応答速度が低下しがちです。
なぜアプリケーションは遅くなるのでしょうか?主な原因の一つは、データベースへの頻繁なアクセスです。
- ユーザーがページを読み込むたびにデータベースからデータを取得する。
- 同じデータが何度も繰り返し要求される。
- 複雑なクエリを実行する必要がある。
このような状況では、データベースサーバーがボトルネックとなり、アプリケーション全体の速度が低下してしまいます。想像してみてください。人気レストランで、全ての注文が入るたびに厨房の奥深くにある冷蔵庫まで取りに行くようなものです。注文が増えれば増えるほど、シェフの移動時間が増え、料理の提供が遅れてしまいます。
この問題を解決するための強力な手法が「キャッシング」です。キャッシングとは、一度取得したデータを、次に必要になったときにすぐに取り出せる場所に一時的に保存しておく仕組みです。これは、レストランの例で言えば、よく使う食材を手元のカウンターに置いておくようなものです。これにより、データベースへのアクセス回数を劇的に減らし、データの取得速度を向上させることができます。
そして、このキャッシングを実現するための非常に強力で一般的なツールの一つが、Redisです。さらに、Microsoft Azureが提供するマネージドサービスであるAzure Redis Cacheを利用すれば、面倒なサーバー管理なしに、このRedisのパワーをアプリケーションに簡単に組み込むことができます。
この記事は、「Azure Redis Cacheを使ったことがない」「キャッシュという概念は知っているけど、具体的にどう使えばいいか分からない」という初心者の方を対象としています。Azure Redis Cacheの基本的な概念から、Azure Portalを使った具体的な作成手順、アプリケーションからの接続方法、基本的な使い方、さらにパフォーマンスを最大限に引き出すための考え方まで、詳しく解説していきます。この記事を読めば、あなたのアプリケーションを劇的に高速化させるための第一歩を踏み出せるはずです。
さあ、Azure Redis Cacheの世界へ飛び込んで、爆速アプリケーション開発の鍵を手に入れましょう!
第1章:RedisとAzure Redis Cacheの基本を知る
まずは、Azure Redis Cacheの基盤となっている「Redis」そのものと、Azureが提供するマネージドサービスとしての「Azure Redis Cache」について理解を深めましょう。
1.1 Redisとは?インメモリデータ構造ストアの力
Redisは、Remote Dictionary Serverの略称で、オープンソースのインメモリデータ構造ストアです。その名の通り、データをディスクではなくメインメモリ上に保持します。これが、Redisが驚異的な速度を誇る最大の理由です。ディスクアクセスに比べてメモリへのアクセスは桁違いに高速です。
Redisは単なるキャッシュシステムではなく、キーと値のペアを扱うNoSQLデータベースの一種と考えることもできます。しかし、一般的なキー・バリュー型ストアと異なるのは、単に文字列を保存するだけでなく、多様なデータ構造をサポートしている点です。
Redisがサポートする主なデータ構造:
- Strings: 最も基本的な型。文字列、整数、浮動小数点数を格納できます。シンプルなキー・バリューキャッシュに使われます。
- Hashes: フィールドと値のペアの集合。オブジェクトを表現するのに適しています。
- Lists: 要素の順序付きコレクション。キューやスタックとして利用できます。
- Sets: 文字列の順序なしコレクション。重複する要素は格納されません。集合演算(和集合、差集合、積集合)が可能です。
- Sorted Sets: スコアによって順序付けられたSet。ランキングなどを実装するのに便利です。
これらの多様なデータ構造を、高速なインメモリ上でネイティブに扱えることが、Redisを単なるキー・バリューキャッシュ以上の存在にしています。セッション情報、ランキング、メッセージキュー、リアルタイム分析など、様々な用途に活用されています。
1.2 Azure Redis Cacheとは?マネージドサービスのメリット
Redisは非常に強力ですが、自分でサーバーを用意してRedisをインストールし、運用・管理するには、いくつかの課題があります。
- 可用性: サーバーが故障した場合の対応。
- スケーラビリティ: アクセス増加に対応するための拡張。
- セキュリティ: 外部からの不正アクセス対策。
- 監視: 正常に動作しているか、パフォーマンスはどうかを常にチェック。
- バックアップ/リストア: データ消失を防ぐための対策。
これらの運用・管理タスクは専門知識が必要で、時間と労力がかかります。ここで登場するのが、Azure Redis Cacheです。
Azure Redis Cacheは、Microsoft Azureが提供するマネージドサービスとしてのRedisです。これはつまり、AzureがRedisサーバーのプロビジョニング、デプロイ、パッチ適用、可用性の確保、スケーリング、監視といった面倒な作業をすべて代行してくれるサービスです。
Azure Redis Cacheを利用する主なメリットは以下の通りです。
- 簡単な導入と管理: Azure Portalから数クリックでインスタンスを作成でき、運用・管理の多くをAzureに任せられます。
- 高い可用性: Azureが冗長構成などを提供し、サービスの停止リスクを最小限に抑えます(プランによる)。
- 容易なスケーリング: アプリケーションの負荷に応じて、キャッシュの容量やパフォーマンスを簡単に拡張・縮小できます。
- Azureエコシステムとの統合: Azureの他のサービス(Web Apps, Virtual Machines, Functionsなど)と連携しやすいです。
- セキュリティ: VNet統合やPrivate Linkなどのセキュリティ機能が利用できます(プランによる)。
- 監視機能: Azure Monitorと連携し、キャッシュの利用状況やパフォーマンスを詳細に監視できます。
自分でRedisを運用するよりも、圧倒的に手間がかからず、安心して利用できるのがAzure Redis Cacheの魅力です。特に、運用リソースが限られている場合や、素早くキャッシュ機能をアプリケーションに組み込みたい場合に最適です。
1.3 なぜキャッシュが必要なのか?Redis Cacheの役割
改めて、なぜアプリケーション開発においてキャッシュが重要なのか、そしてAzure Redis Cacheがどのような役割を果たすのかを整理しましょう。
アプリケーションのデータフローは、一般的に「ユーザーのリクエスト」→「アプリケーションサーバー」→「データベース」という流れになります。
ユーザーのリクエスト → アプリケーションサーバー → データベース
↑ ↓
←────────────── データ応答
この図において、データベースへのアクセスが頻繁かつ重い処理である場合、その部分がボトルネックとなります。
ここにAzure Redis Cacheを導入すると、データフローは以下のようになります。
ユーザーのリクエスト → アプリケーションサーバー ─┬→ データベース
│ ↑
│ │ (キャッシュに無い場合のみ)
↓ ↓
Azure Redis Cache ─ データ応答
↑ │
└──────────┘ (キャッシュにヒットした場合)
アプリケーションサーバーは、まずデータをRedis Cacheに問い合わせます。
- キャッシュヒット: 欲しいデータがキャッシュにあれば(「キャッシュヒット」)、データベースにアクセスすることなく、キャッシュから即座にデータを取得し、ユーザーに返します。これは非常に高速です。
- キャッシュミス: 欲しいデータがキャッシュになければ(「キャッシュミス」)、データベースにアクセスしてデータを取得します。取得したデータは、次に同じデータが必要になったときのために、キャッシュに保存しておきます。
このように、Azure Redis Cacheはアプリケーションサーバーとデータベースの間に位置し、よく使うデータや計算結果を一時的に保持することで、データベースへの負荷を軽減し、アプリケーションの応答速度を向上させる役割を担います。
1.4 Azure Redis Cacheを使うべき代表的なシナリオ
Azure Redis Cacheは様々なシナリオで威力を発揮します。初心者向けに、いくつか代表的な例を挙げます。
- Webアプリケーションのセッション状態管理: ユーザーがログインした状態を保持するためのセッション情報をRedis Cacheに保存することで、Webサーバーがスケールしてもセッションが維持され、データベースへの負荷も軽減できます。
- 頻繁にアクセスされるデータのキャッシュ: 商品情報、設定情報、ランキングデータなど、読み取り頻度が高いが更新頻度が低いデータをキャッシュすることで、ページの表示速度を向上させます。
- ランキングやリーダーボード: Sorted SetなどのRedisのデータ構造を活用して、リアルタイムなランキングを効率的に実装できます。
- メッセージキュー: Listデータ構造を利用して、簡単な非同期処理のためのメッセージキューとして利用できます。
- レート制限: 特定の操作(例: API呼び出し)の回数をユーザーごとやIPアドレスごとに制限するために使用できます。
- Publish/Subscribe (Pub/Sub) メカニズム: リアルタイムのイベント通知システムなどを構築できます。
これらのシナリオ以外にも、Redisの多様なデータ構造と高速性を活かせる場面は多々あります。まずは最も一般的なキャッシュとして使い始めるのが良いでしょう。
第2章:Azure Redis Cacheのプランと選び方
Azure Redis Cacheには、いくつかの異なる価格レベル(プラン)があります。それぞれのプランで提供される機能やパフォーマンス、料金が異なりますので、アプリケーションの要件や予算に合わせて適切なプランを選択することが重要です。
主なプランは以下の通りです。
- Basic
- Standard
- Premium
- Enterprise
- Enterprise Flash
ここでは、初心者の方がまず検討するであろうBasic, Standard, Premiumプランを中心に解説します。Enterpriseプランは比較的新しく、Redis Enterpriseが持つ高度な機能(Modulesなど)を利用できますが、ここでは概要のみ触れます。
2.1 各プランの機能比較(Basic, Standard, Premium)
| 機能/項目 | Basicプラン | Standardプラン | Premiumプラン |
|---|---|---|---|
| SLA (サービスレベルアグリーメント) | なし | 99.9% | 99.9% |
| 可用性 | 単一ノード | 2ノード(プライマリ/レプリカ) | 2ノード(プライマリ/レプリカ) |
| データ永続化 | なし | なし | あり (RDB / AOF) |
| Redis Cluster | なし | なし | あり |
| VNet サポート | なし | なし | あり |
| ゾーン冗長 | なし | なし | あり |
| Private Link | なし | なし | あり |
| Redis Modules | なし | なし | 一部利用可能(非保証) |
| SSL接続 | あり | あり | あり |
| 非SSL接続 | あり(デフォルト有効) | あり(デフォルト有効) | あり(デフォルト無効) |
| 推奨される用途 | 開発/テスト、非クリティカルなアプリ | 本番環境(可用性が必要な場合) | 大規模本番環境、高性能/高可用性、追加機能が必要な場合 |
Basicプラン:
- 最も安価なプランで、開発やテスト、またはキャッシュが失われても問題ないような非常に非クリティカルな用途に適しています。
- 単一ノード構成のため、ノードに障害が発生するとキャッシュが利用できなくなります。SLAもありません。
Standardプラン:
- 本番環境での利用を想定した最も一般的なプランです。
- プライマリ/レプリカの2ノード構成になっており、プライマリノードに障害が発生した場合、レプリカノードがプライマリに昇格することでサービスが継続されます。これにより99.9%のSLAが提供されます。
- データ永続化やクラスタリングといった高度な機能は含まれません。
Premiumプラン:
- 高性能・高可用性が求められるミッションクリティカルな本番環境向けのプランです。
- Standardプランの機能に加え、データ永続化(RDBまたはAOF)、Redis Clusterによるスケールアウト、Azure Virtual Network (VNet) 統合、ゾーン冗長、Private Linkといった重要な機能が利用できます。
- VNet統合やPrivate Linkは、セキュリティを高める上で非常に重要です。
Enterprise / Enterprise Flash プラン:
- Redis Enterpriseソフトウェアをベースにした、より高度な機能(Redis Modulesのサポートなど)と高いパフォーマンス、可用性を提供するプランです。
- Enterprise Flashは、DRAMとNVM (不揮発性メモリ) を組み合わせてコストとパフォーマンスのバランスを取っています。
- 非常に大規模なワークロードや、特定のRedis Enterprise機能が必要な場合に検討します。初心者向けのこの記事では詳細な説明は割愛します。
2.2 適切なプランの選び方
初心者の方がプランを選択する際の一般的な指針をいくつかご紹介します。
- 開発・テスト段階: まずは一番安価なBasicプランから始めましょう。キャッシュの基本的な使い方を学ぶには十分です。
- 小~中規模の本番環境で、ある程度の可用性が必要: Standardプランが最もバランスが取れています。ほとんどのWebアプリケーションのキャッシュ要件を満たせるでしょう。
- 大規模な本番環境、高いパフォーマンス/可用性、セキュリティ、または追加機能(永続化、クラスタリング、VNet統合)が必要: Premiumプランを検討しましょう。特にセキュリティのためにVNet内に配置したい場合はPremiumが必須です。
- 扱うデータが非常に巨大で単一ノードでは収まらない、またはRedis Enterprise独自の機能が必要: EnterpriseまたはEnterprise Flashプランを検討します(ただし、これらは初心者向けというよりは高度なトピックになります)。
迷ったらまずはStandardプランで始めてみて、必要に応じてPremiumプランにアップグレードするのが良いアプローチです。プランは後から変更可能ですが、BasicからStandard/Premium、またはStandardからPremiumへのアップグレードは、キャッシュの再起動や再構築が発生し、一時的なダウンタイムやデータ損失の可能性があることに注意が必要です。
2.3 料金体系の概要
Azure Redis Cacheの料金は、主に以下の要素で決まります。
- 選択したプラン: プランによって基本料金が大きく異なります。
- キャッシュサイズ: プラン内で選択できるキャッシュの容量(例: 250MB, 1GB, 6GB, …) によって料金が変わります。一般的に容量が大きいほど高価になります。
- リージョン: サービスをデプロイするAzureのリージョンによって料金が異なる場合があります。
料金は時間単位で発生します。Azureの料金計算ツールを使って、見積もりを確認することをお勧めします。
第3章:Azure Portalを使ったAzure Redis Cacheの作成
それでは実際にAzure Portalを使ってAzure Redis Cacheのインスタンスを作成してみましょう。Azureアカウントをお持ちでない場合は、事前に作成してください(無料トライアルでも可能です)。
3.1 Azure Portal にサインインし、リソースを作成
- Azure Portal (portal.azure.com) にサインインします。
- 左上の「≡」アイコンをクリックし、メニューを開きます。
- メニューから「+ リソースの作成」を選択します。
3.2 Azure Redis Cache を検索し、選択
- 「リソースの作成」ページの検索ボックスに「Azure Cache for Redis」と入力します。
- 検索結果に表示される「Azure Cache for Redis」を選択します。
- 表示されたページで「作成」ボタンをクリックします。
3.3 基本設定の入力
Azure Cache for Redis の作成ウィザードが表示されます。最初のステップ「基本」タブで、必要な情報を入力します。
- サブスクリプション: 利用するAzureサブスクリプションを選択します。通常はデフォルトで問題ありません。
- リソース グループ: キャッシュを配置するリソースグループを選択または新規作成します。リソースグループは、Azureリソースを論理的にまとめるためのコンテナです。アプリケーションごとにリソースグループを分けると管理しやすくなります。「新規作成」をクリックして、分かりやすい名前(例:
my-redis-cache-rg)を入力し、「OK」をクリックするのがおすすめです。 - DNS 名: キャッシュインスタンスの一意な名前を入力します。この名前が、アプリケーションから接続する際のホスト名の一部になります。Azure全体で一意である必要があり、小文字の英数字とハイフンのみ使用できます。入力すると、横に利用可能かどうかが表示されます(例:
my-unique-redis-cache-007)。 - 場所 (リージョン): キャッシュをデプロイするAzureリージョンを選択します。アプリケーションサーバーやデータベースが配置されているリージョンと同じか、地理的に近いリージョンを選択することで、ネットワーク遅延を最小限に抑えられます。日本の場合は「Japan East」や「Japan West」を選択します。
- 価格レベル: 前章で解説したプラン(Basic, Standard, Premium, …)を選択します。ここでは例として「Standard C1 (1 GB)」を選択してみましょう。プランを選択すると、そのプランの簡単な説明とキャッシュサイズが表示されます。プルダウンを開いて、希望のプランとサイズを選択してください。
- キャッシュの種類: 「Redis Cache (独立版)」を選択します。Enterprise/Enterprise Flashは「Redis Enterprise Cache」を選択しますが、ここでは独立版で十分です。
基本設定の入力が終わったら、「次へ: 詳細」をクリックします。
3.4 詳細設定(プランによって表示が異なります)
このタブの設定は、選択したプランによって表示内容が大きく異なります。Basicプランではほとんどオプションがありませんが、StandardやPremiumプランではいくつかの設定が可能です。
ここではStandardプランを想定して解説します。
-
ポート:
- SSL ポート (6380): SSL/TLS暗号化を使用した接続を有効にするかを選択します。セキュリティのため、本番環境では必ず有効(チェックを入れる)にしてください。
- 非 SSL ポート (6379): 暗号化なしの接続を有効にするかを選択します。本番環境ではセキュリティ上のリスクがあるため、無効(チェックを外す)にすることを強く推奨します。 初心者向けのローカル開発環境などで一時的に使う場合は有効にしても構いませんが、基本的にはSSLを使用するようにしましょう。
-
Redis バージョン: 利用するRedisのバージョンを選択します。特別な理由がない限り、推奨されている最新バージョンを選択するのが良いでしょう。
-
Redis 用の非アクティブ期間中の暗号化 (データ保護): Premiumプラン以上で利用可能な機能で、キャッシュ内のデータをストレージに保存する際に暗号化するかどうかを設定します。セキュリティ要件に応じて有効化します。
Basicプランでは、SSL/非SSLポートの設定のみが表示されることが多いです。Premiumプランでは、これらに加えて、VNet統合、Redis Cluster、永続化などの設定項目が表示されます。初心者向けとしては、まずはSSLポートを有効化し、非SSLポートを無効化する設定に注目すれば十分です。
詳細設定が終わったら、「次へ: ネットワーク」をクリックします。
3.5 ネットワーク設定(Premiumプラン以上で重要)
このタブは、特にPremiumプラン以上でVNet統合やPrivate Linkを利用する場合に重要になります。
- 接続方法:
- パブリック エンドポイント (DNS 名): デフォルトの選択肢です。インターネット経由でキャッシュにアクセスします。セキュリティのためにアクセスキーとSSL接続、そしてファイアウォール設定が重要になります。
- プライベート エンドポイント: Azure VNet内にキャッシュのプライベートIPアドレスを作成し、VNet内からのみアクセス可能にします。セキュリティレベルが最も高くなります。Premiumプラン以上で利用可能です。
- Virtual Network: キャッシュを既存のAzure VNetに直接参加させます。VNet内のリソースからのアクセスを容易にし、セキュリティも向上します。Premiumプラン以上で利用可能です。
初心者の方は、まずはパブリック エンドポイントを選択して開始するのが最も簡単です。セキュリティを高めたい場合は、後からPrivate Endpointなどを構成することを検討しましょう。
ネットワーク設定が終わったら、「次へ: 高度」をクリックします。
3.6 高度な設定(Premiumプラン以上で重要)
このタブもPremiumプラン以上の高度な機能に関する設定が多く含まれます。
- Redis Cluster: Premiumプラン以上で利用可能です。データを複数のRedisノードに分散させ、単一のキャッシュサイズの上限を超えるデータ容量を扱ったり、スループットを向上させたりできます。
- 非永続化: Basic/Standardプランでは選択できません。Premiumプラン以上では、データの永続化(RDBまたはAOF)を設定できます。
- RDB スナップショット: ある時点のデータセットをディスクに保存します。高速ですが、最後のスナップショット以降のデータは失われる可能性があります。
- AOF (Append Only File): 全ての書き込みコマンドをログとして記録します。RDBよりもデータの欠損リスクが少ないですが、ファイルサイズが大きくなりやすいです。
- Microsoft Entra ID (旧 Azure AD) 認証: アクセスキーではなく、Microsoft Entra IDのID/パスワードやマネージドIDを使って認証できるようにする設定です。セキュリティを高めるためのオプションです。
初心者の方は、基本的にはデフォルト設定のままで問題ありません。必要に応じて、後からこれらの機能を有効化することを検討します。
高度な設定が終わったら、「次へ: タグ」をクリックします。
3.7 タグの設定(オプション)
タグは、Azureリソースを分類するためのキー・バリューペアです。コスト管理やリソースの識別に役立ちます。例えば、「Environment: Development」「Project: MyWebApp」のようなタグを設定できます。必須ではありませんが、適切に設定すると後々管理が楽になります。
タグの設定が終わったら、「次へ: レビュー + 作成」をクリックします。
3.8 設定内容の確認と作成
最後のステップです。これまで入力した設定内容が表示されます。内容を確認し、問題がなければ「作成」ボタンをクリックします。
AzureがRedis Cacheインスタンスのデプロイを開始します。デプロイには数分かかる場合があります。完了すると、「デプロイが成功しました」という通知が表示されます。
3.9 作成後のリソース確認
デプロイが完了したら、「リソースに移動」ボタンをクリックするか、Azure Portalの検索ボックスで作成したキャッシュ名を検索して、作成したAzure Cache for Redisインスタンスの概要ページに移動します。
概要ページでは、キャッシュのステータス(実行中であることを確認)、DNS名、場所、価格レベルなどが確認できます。
これで、Azure Redis Cacheインスタンスの作成は完了です!次は、アプリケーションからこのキャッシュに接続するための情報を取得しましょう。
第4章:アプリケーションからの接続情報を取得する
アプリケーションからAzure Redis Cacheに接続するには、いくつかの情報が必要です。最も重要なのは「ホスト名」と「アクセスキー」です。これらの情報は、作成したキャッシュインスタンスのAzure Portalのページから取得できます。
- 作成したAzure Cache for Redisインスタンスの概要ページを開きます。
- 左側のメニューから「アクセス キー」を選択します。
このページに、アプリケーションからの接続に必要な情報が表示されています。
- ホスト名: アプリケーションから接続する際のエンドポイントとなる名前です。(例:
my-unique-redis-cache-007.redis.cache.windows.net) - プライマリ接続文字列 (StackExchange.Redis): 後述する.NETクライアントライブラリ「StackExchange.Redis」用の接続文字列です。ホスト名、ポート、パスワード(アクセスキー)などが含まれています。
- セカンダリ接続文字列 (StackExchange.Redis): プライマリと同様ですが、セカンダリのアクセスキーが使われます。
- プライマリ キー: キャッシュへの接続に使用するパスワードです。このキーは非常に重要であり、外部に漏れないように厳重に管理してください。 アプリケーションの構成ファイルや環境変数などに安全に格納する必要があります。
- セカンダリ キー: プライマリキーと同様に使用できる別のパスワードです。プライマリキーを更新(再生成)する際に、ダウンタイムなしでキーを切り替えるために使用できます。
注意点:
- アクセスキーの管理: アクセスキーはキャッシュへの完全なアクセス権を持つパスワードです。ソースコードに直接埋め込むことは絶対に避け、Azure Key Vaultやアプリケーションの設定管理機能など、安全な方法で管理してください。
- キーの再生成: セキュリティ上の理由から、定期的にアクセスキーを再生成することを検討してください。「キーの再生成」ボタンから行えます。再生成する際は、まずセカンダリキーをアプリケーションの設定で使用するように変更・デプロイし、問題がなければプライマリキーを再生成し、最後にアプリケーションの設定を新しいプライマリキーに戻す(またはセカンダリキーを新しいものに更新する)という手順を踏むと、ダウンタイムを最小限に抑えられます。
また、概要ページの左側メニューにある「プロパティ」を選択すると、SSLポート番号(デフォルト: 6380)、非SSLポート番号(デフォルト: 6379)、Redisバージョンなどが確認できます。アプリケーションからの接続設定の際に必要になることがあります。特にSSLポート番号は重要です。
第5章:アプリケーションからの接続方法(C# .NET コード例)
次に、実際にプログラミング言語を使ってAzure Redis Cacheに接続し、基本的な操作を行う方法を解説します。ここでは、Azure開発でよく使われるC# (.NET) を例に、最も一般的なクライアントライブラリであるStackExchange.Redisを使った方法を詳しく説明します。他の言語についても簡単に触れます。
5.1 StackExchange.Redis ライブラリの導入 (.NET)
StackExchange.Redisは、.NETアプリケーションからRedisに接続するための高性能で信頼性の高いライブラリです。NuGetパッケージマネージャーを使ってプロジェクトに追加します。
Visual Studioの場合:
- プロジェクトのソリューションエクスプローラーでプロジェクトを右クリックし、「NuGet パッケージの管理…」を選択します。
- 「参照」タブを選択し、検索ボックスに「StackExchange.Redis」と入力します。
- 検索結果に表示される「StackExchange.Redis」を選択し、「インストール」ボタンをクリックします。
.NET CLIの場合:
bash
dotnet add package StackExchange.Redis
5.2 接続文字列の構成
Azure Portalの「アクセス キー」ページで確認できる「プライマリ接続文字列 (StackExchange.Redis)」は、StackExchange.Redisが直接使用できる形式になっています。しかし、ホスト名、ポート、パスワードを個別に設定したい場合や、他のオプション(SSL有効化、タイムアウト設定など)を追加したい場合は、自分で接続文字列を構成します。
基本的な接続文字列の形式:
<ホスト名>,abortConnect=false,ssl=true,password=<アクセスキー>
<ホスト名>: Azure Portalの「アクセス キー」ページで確認したホスト名。(例:my-unique-redis-cache-007.redis.cache.windows.net)abortConnect=false: Redisインスタンスにすぐに接続できない場合でも、エラーを発生させずに接続オブジェクトを作成します。これは、バックグラウンドで再接続を試みるため、特にアプリケーションの起動時に接続できない場合でもアプリケーションがクラッシュしないようにするために重要です。ssl=true: SSL/TLS暗号化を使用して接続することを指定します。Azure Redis CacheではセキュリティのためにSSL接続を強く推奨しており、デフォルトでSSLポート(6380)が有効になっています。非SSL接続を有効にしている場合でも、本番環境では必ずssl=trueを指定してください。password=<アクセスキー>: Azure Portalで取得したアクセスキーを指定します。
例:
csharp
string connectionString = "my-unique-redis-cache-007.redis.cache.windows.net,abortConnect=false,ssl=true,password=YOUR_ACCESS_KEY";
YOUR_ACCESS_KEYの部分は、Azure Portalで取得したプライマリキーまたはセカンダリキーに置き換えてください。この接続文字列は、アプリケーションの構成ファイル(例: appsettings.json)や環境変数から読み込むようにしてください。ソースコードに直接書き込むのは避けましょう。
5.3 ConnectionMultiplexer の使い方 (シングルトンパターン)
StackExchange.RedisでRedisに接続するには、ConnectionMultiplexerクラスを使用します。このクラスは、Redisサーバーへの物理的な接続を管理し、複数のスレッド間で安全に共有できるように設計されています。
非常に重要な点として、ConnectionMultiplexerインスタンスはアプリケーション全体で単一のインスタンスを使い回す(シングルトンパターンで管理する)べきです。 リクエストごとに新しいConnectionMultiplexerを作成すると、接続の確立にコストがかかり、ポート枯渇などの問題を引き起こす可能性があります。
以下は、シングルトンパターンでConnectionMultiplexerを管理する基本的な例です。
“`csharp
using StackExchange.Redis;
using System;
public class RedisConnection
{
private static ConnectionMultiplexer _instance;
private static readonly object _lockObject = new object();
private static string _connectionString;
// アプリケーション起動時に接続文字列を設定する
public static void Initialize(string connectionString)
{
_connectionString = connectionString;
}
// ConnectionMultiplexerのインスタンスを取得する (シングルトン)
public static ConnectionMultiplexer Connection
{
get
{
if (_instance == null || !_instance.IsConnected)
{
lock (_lockObject)
{
if (_instance == null || !_instance.IsConnected)
{
if (string.IsNullOrEmpty(_connectionString))
{
throw new InvalidOperationException("RedisConnection is not initialized. Call Initialize() first.");
}
Console.WriteLine("Creating new Redis ConnectionMultiplexer...");
_instance = ConnectionMultiplexer.Connect(_connectionString);
// オプション: 接続状態の変化をログに出力
_instance.ConnectionFailed += (_, e) => Console.WriteLine($"Connection failed: {e.Exception.Message}");
_instance.ConnectionRestored += (_, e) => Console.WriteLine($"Connection restored");
_instance.ErrorMessage += (_, e) => Console.WriteLine($"Redis Error: {e.Message}");
_instance.ConfigurationChanged += (_, e) => Console.WriteLine($"Configuration changed");
_instance.HashSlotMoved += (_, e) => Console.WriteLine($"Hash slot moved");
_instance.InternalError += (_, e) => Console.WriteLine($"Internal error: {e.Exception.Message}");
}
}
}
return _instance;
}
}
// アプリケーション終了時に接続をクリーンアップする
public static void Close()
{
if (_instance != null)
{
_instance.Dispose();
_instance = null;
}
}
}
“`
アプリケーションの起動処理(例: ASP.NET Coreの Startup.cs や Program.cs)で RedisConnection.Initialize() を呼び出し、シャットダウン処理で RedisConnection.Close() を呼び出すように構成します。
例: ASP.NET Core (.NET 6以降のMinimal APIスタイル)
“`csharp
using StackExchange.Redis;
// … 既存のusingディレクティブ …
var builder = WebApplication.CreateBuilder(args);
// Configure Redis ConnectionMultiplexer as a singleton
string redisConnectionString = builder.Configuration.GetConnectionString(“RedisCacheConnection”);
if (string.IsNullOrEmpty(redisConnectionString))
{
throw new InvalidOperationException(“RedisCacheConnection connection string is not configured.”);
}
RedisConnection.Initialize(redisConnectionString);
// ConnectionMultiplexerをシングルトンとしてDIコンテナに登録する場合
// builder.Services.AddSingleton
// … 既存のサービス登録 …
var app = builder.Build();
// … 既存のミドルウェア構成 …
// アプリケーションシャットダウン時にRedis接続を閉じる
app.Lifetime.ApplicationStopping.Register(() =>
{
RedisConnection.Close();
Console.WriteLine(“Redis ConnectionMultiplexer closed.”);
});
// APIエンドポイントなどでRedisを使用する例
app.MapGet(“/cache/{key}”, async (string key) =>
{
var db = RedisConnection.Connection.GetDatabase(); // DBインスタンスを取得
string value = await db.StringGetAsync(key); // キーを非同期で取得
if (value == null)
{
return Results.NotFound($"Key '{key}' not found in cache.");
}
return Results.Ok($"Value for key '{key}': {value}");
});
app.MapPost(“/cache/{key}”, async (string key, [FromBody] string value) =>
{
var db = RedisConnection.Connection.GetDatabase(); // DBインスタンスを取得
bool set = await db.StringSetAsync(key, value, TimeSpan.FromMinutes(10)); // キーをセット、有効期限10分
if (set)
{
return Results.Created($"/cache/{key}", $"Key '{key}' set successfully with value '{value}'. Expires in 10 minutes.");
}
else
{
// 設定失敗 (Redis側でエラーなど)
return Results.StatusCode(500, $"Failed to set key '{key}'.");
}
});
app.Run();
“`
appsettings.json に接続文字列を定義します。
json
{
"ConnectionStrings": {
"RedisCacheConnection": "my-unique-redis-cache-007.redis.cache.windows.net,abortConnect=false,ssl=true,password=YOUR_ACCESS_KEY"
},
// ... その他の設定 ...
}
5.4 IDatabase オブジェクトの取得
ConnectionMultiplexerインスタンスが取得できたら、そこからIDatabaseオブジェクトを取得して実際のRedisコマンドを実行します。
csharp
IDatabase db = RedisConnection.Connection.GetDatabase();
// または、依存性注入を使う場合:
// IDatabase db = _connectionMultiplexer.GetDatabase();
GetDatabase() メソッドには引数を渡すことができますが、通常はデフォルト(データベース0)を使用するため、引数なしで呼び出すことが多いです。Redisでは、複数の論理データベース(0から15まで、デフォルト16個)を持つことができますが、Azure Redis Cacheでは単一のデータベースが推奨されています。
5.5 基本的なキャッシュ操作 (String型)
最も基本的なキャッシュ操作は、キーに対応する値を保存(Set)し、取得(Get)し、削除(Delete)することです。これらはRedisのString型として扱われます。StackExchange.Redisでは非同期メソッドが用意されており、I/O処理中にアプリケーションのスレッドをブロックしないように非同期メソッドを使用することが推奨されます。
“`csharp
using StackExchange.Redis;
using System;
using System.Threading.Tasks;
// … RedisConnection クラスと初期化済み ConnectionMultiplexer があると仮定 …
public class CacheService
{
private readonly IDatabase _database;
public CacheService()
{
// シングルトンからIDatabaseを取得
_database = RedisConnection.Connection.GetDatabase();
}
// キャッシュにデータを設定する
public async Task SetCacheAsync(string key, string value, TimeSpan? expiry = null)
{
// keyとvalueはRedisValue型に暗黙的に変換される
// expiry はオプション。指定しない場合は永続化される(ただし、メモリ制限やエビクションに注意)
bool result = await _database.StringSetAsync(key, value, expiry);
if (result)
{
Console.WriteLine($"Key '{key}' set successfully.");
}
else
{
Console.WriteLine($"Failed to set key '{key}'.");
}
}
// キャッシュからデータを取得する
public async Task<string> GetCacheAsync(string key)
{
// キーが存在しない場合は RedisValue.Null が返される
RedisValue value = await _database.StringGetAsync(key);
if (value.IsNull)
{
Console.WriteLine($"Key '{key}' not found.");
return null;
}
else
{
Console.WriteLine($"Key '{key}' found. Value: {value}");
return value.ToString(); // RedisValueからstringに変換
}
}
// キャッシュからデータを削除する
public async Task<bool> DeleteCacheAsync(string key)
{
bool deleted = await _database.KeyDeleteAsync(key);
if (deleted)
{
Console.WriteLine($"Key '{key}' deleted successfully.");
}
else
{
Console.WriteLine($"Key '{key}' not found or failed to delete.");
}
return deleted;
}
// キーの有効期限を設定または更新する
public async Task<bool> SetKeyExpirationAsync(string key, TimeSpan expiry)
{
bool success = await _database.KeyExpireAsync(key, expiry);
if (success)
{
Console.WriteLine($"Key '{key}' expiration set to {expiry}.");
}
else
{
Console.WriteLine($"Failed to set expiration for key '{key}'. Key might not exist.");
}
return success;
}
}
“`
使い方:
“`csharp
var cacheService = new CacheService();
// データのセット(10分で期限切れ)
await cacheService.SetCacheAsync(“mykey”, “myvalue”, TimeSpan.FromMinutes(10));
// データの取得
string cachedValue = await cacheService.GetCacheAsync(“mykey”);
Console.WriteLine($”Retrieved value: {cachedValue}”); // myvalue が表示されるはず
// データを削除
await cacheService.DeleteCacheAsync(“mykey”);
// 再度取得を試みる
cachedValue = await cacheService.GetCacheAsync(“mykey”);
Console.WriteLine($”Retrieved value after deletion: {cachedValue}”); // null が表示されるはず
// 期限切れのテスト
await cacheService.SetCacheAsync(“expiringkey”, “value”, TimeSpan.FromSeconds(5));
Console.WriteLine(“Waiting 6 seconds for key to expire…”);
await Task.Delay(6000);
cachedValue = await cacheService.GetCacheAsync(“expiringkey”);
Console.WriteLine($”Retrieved value after expiration: {cachedValue}”); // null が表示されるはず
“`
5.6 他のプログラミング言語でのクライアントライブラリ
Azure Redis CacheはオープンソースのRedisと完全に互換性があるため、各言語で提供されている標準的なRedisクライアントライブラリを使用できます。
- Java: Jedis, Lettuce
- Python: redis-py
- Node.js: ioredis, node_redis
- PHP: predis, phpredis
- Go: go-redis/redis
これらのライブラリでも、接続文字列やホスト名、ポート、パスワード(アクセスキー)を使って接続し、対応するメソッド(Set, Get, Delなど)を呼び出すことでRedis操作を行います。各ライブラリのドキュメントを参照してください。基本的な使い方はC#の場合と概念的に同じです。
Node.js (ioredis) の例:
“`javascript
import Redis from ‘ioredis’;
// 接続文字列から情報を抽出するか、個別に指定
const redis = new Redis({
port: 6380, // SSLポート (通常 6380)
host: ‘my-unique-redis-cache-007.redis.cache.windows.net’,
password: ‘YOUR_ACCESS_KEY’,
tls: {
rejectUnauthorized: false // 本番環境では適切に証明書を検証してください
}
});
redis.on(‘connect’, () => {
console.log(‘Connected to Redis’);
});
redis.on(‘error’, (err) => {
console.error(‘Redis error:’, err);
});
// キャッシュ操作の例 (Async/Await)
async function cacheExample() {
try {
// データのセット (期限なし)
await redis.set(‘mykey_node’, ‘myvalue_node’);
console.log(“Key ‘mykey_node’ set.”);
// データのセット (期限付き - 60秒)
await redis.set('expiringkey_node', 'value_node', 'EX', 60);
console.log("Key 'expiringkey_node' set with expiration.");
// データの取得
const value = await redis.get('mykey_node');
console.log(`Value for 'mykey_node': ${value}`);
// データの削除
const deletedCount = await redis.del('mykey_node');
console.log(`Deleted ${deletedCount} keys.`);
// 削除後の取得を試みる
const valueAfterDelete = await redis.get('mykey_node');
console.log(`Value for 'mykey_node' after delete: ${valueAfterDelete}`); // null
} catch (error) {
console.error(‘Error during cache operation:’, error);
} finally {
// 必要であれば接続を閉じますが、通常はアプリケーションのライフタイム中は開いたままにします
// redis.quit();
}
}
cacheExample();
“`
重要なのは、どの言語を使うにしても、ホスト名、ポート(通常はSSLポート6380)、そしてアクセスキー(パスワード)が必要になるという点です。そして、本番環境では必ずSSL/TLS暗号化を有効にして接続してください。
第6章:Redisのデータ構造と基本的なコマンド(応用編への一歩)
Redisが強力なのは、単なるキー・バリューキャッシュではなく、様々なデータ構造をサポートしている点です。これらのデータ構造を理解することで、より多様なキャッシュ戦略や機能実装が可能になります。ここでは、主要なデータ構造と、それに対応するRedisコマンド(やクライアントライブラリのメソッド)の基本的な使い方を紹介します。
Azure Redis Cacheに接続してコマンドを実行するには、StackExchange.Redisの場合 IDatabase インターフェースを使います。各Redisコマンドに対応するメソッドが用意されています(例: SET コマンドに対応する StringSetAsync メソッド)。
6.1 String 型
- 用途: 最も基本的。文字列、整数、浮動小数点数を格納。シンプルなキー・バリューキャッシュ、カウンタ、セッション情報など。
-
コマンド例:
SET key value [EX seconds]: キーに値を設定する。EXオプションで有効期限を秒単位で指定できる。GET key: キーの値を取得する。キーが存在しない場合はnil(StackExchange.RedisではRedisValue.Null)を返す。MSET key1 value1 key2 value2 ...: 複数のキーにまとめて値を設定する。MGET key1 key2 ...: 複数のキーの値をまとめて取得する。INCR key: キーの値を1増やす(キーが存在しない場合は0として扱う)。カウンタの実装に便利。DECR key: キーの値を1減らす。EXPIRE key seconds: 既存のキーに有効期限を秒単位で設定する。TTL key: キーの残り有効期間を秒単位で取得する。
-
C# (StackExchange.Redis) 例:
“`csharp
await _database.StringSetAsync(“visits”, “0”); // SET
await _database.StringIncrementAsync(“visits”); // INCR
await _database.StringIncrementAsync(“visits”); // INCR
Console.WriteLine($”Visits: {await _database.StringGetAsync(“visits”)}”); // GET -> 2await _database.StringSetAsync(“greeting”, “Hello”, TimeSpan.FromSeconds(60)); // SET with EX
await _database.KeyExpireAsync(“anotherkey”, TimeSpan.FromMinutes(5)); // EXPIRE
“`
6.2 Hash 型
- 用途: オブジェクトやレコードを表現するのに適している。ユーザー情報、商品詳細など、関連する複数のフィールドと値を持つデータをまとめて格納できる。
-
コマンド例:
HSET key field value [field value ...]: ハッシュに1つ以上のフィールドと値を設定する。HGET key field: ハッシュから特定のフィールドの値を取得する。HGETALL key: ハッシュの全フィールドと値を取得する。HDEL key field [field ...]: ハッシュから1つ以上のフィールドを削除する。HKEYS key: ハッシュの全フィールド名を取得する。HVALS key: ハッシュの全値を取得する。
-
C# (StackExchange.Redis) 例:
“`csharp
var userHash = new HashEntry[] {
new HashEntry(“name”, “Alice”),
new HashEntry(“age”, “30”),
new HashEntry(“city”, “Tokyo”)
};
await _database.HashSetAsync(“user:123”, userHash); // HSETRedisValue userName = await _database.HashGetAsync(“user:123”, “name”); // HGET -> Alice
Console.WriteLine($”User name: {userName}”);HashEntry[] allUserInfo = await _database.HashGetAllAsync(“user:123″); // HGETALL
foreach(var entry in allUserInfo)
{
Console.WriteLine($”{entry.Name}: {entry.Value}”); // name: Alice, age: 30, city: Tokyo
}await _database.HashDeleteAsync(“user:123”, “city”); // HDEL
“`
6.3 List 型
- 用途: 要素の順序付きコレクション。キュー、スタック、最近のアイテムリストなどに利用できる。リストの両端から高速に要素を追加・削除できる。
-
コマンド例:
LPUSH key element [element ...]: リストの左端(先頭)に1つ以上の要素を追加する。RPUSH key element [element ...]: リストの右端(末尾)に1つ以上の要素を追加する。LPOP key: リストの左端から要素を1つ取り出し、削除する。RPOP key: リストの右端から要素を1つ取り出し、削除する。LRANGE key start stop: リストの指定した範囲の要素を取得する。負のインデックスも使える(-1は最後の要素)。LLEN key: リストの要素数を取得する。
-
C# (StackExchange.Redis) 例:
“`csharp
await _database.ListLeftPushAsync(“tasks”, “Task 1”); // LPUSH
await _database.ListRightPushAsync(“tasks”, “Task 2”); // RPUSH
await _database.ListLeftPushAsync(“tasks”, “Task 0”); // LPUSH -> List is now [“Task 0”, “Task 1”, “Task 2”]RedisValue firstTask = await _database.ListLeftPopAsync(“tasks”); // LPOP -> “Task 0”, List is now [“Task 1”, “Task 2″]
Console.WriteLine($”First task: {firstTask}”);RedisValue[] recentTasks = await _database.ListRangeAsync(“tasks”, 0, -1); // LRANGE all elements
Console.WriteLine($”Recent tasks: {string.Join(“, “, recentTasks)}”); // Task 1, Task 2
“`
6.4 Set 型
- 用途: 文字列の順序なしコレクション。重複する要素は含まれない。タグ、いいね!、グループメンバーなどの管理、要素の存在チェック。
-
コマンド例:
SADD key member [member ...]: セットに1つ以上の要素を追加する。SMEMBERS key: セットの全要素を取得する。SREM key member [member ...]: セットから1つ以上の要素を削除する。SISMEMBER key member: 指定した要素がセットに存在するかどうかをチェックする(存在するなら1、しないなら0)。SCARD key: セットの要素数を取得する。SINTER key1 key2 ...: 複数のセットの共通要素(積集合)を取得する。
-
C# (StackExchange.Redis) 例:
“`csharp
await _database.SetAddAsync(“tags:article:1001”, new RedisValue[] { “Azure”, “Redis”, “Cache”, “Azure” }); // SADD, “Azure” is added only onceRedisValue[] articleTags = await _database.SetMembersAsync(“tags:article:1001”); // SMEMBERS -> { “Azure”, “Redis”, “Cache” } (order is not guaranteed)
Console.WriteLine($”Article tags: {string.Join(“, “, articleTags)}”);bool isAzureTagPresent = await _database.SetIsMemberAsync(“tags:article:1001”, “Azure”); // SISMEMBER -> true
Console.WriteLine($”Is ‘Azure’ tag present? {isAzureTagPresent}”);await _database.SetRemoveAsync(“tags:article:1001”, “Cache”); // SREM
“`
6.5 Sorted Set 型
- 用途: 要素に「スコア」と呼ばれる数値を関連付けたSet。スコアによって要素が自動的にソートされる。ランキング、ゲームのスコアボード、タイムラインなど。
-
コマンド例:
ZADD key score member [score member ...]: ソート済みセットに1つ以上の要素とスコアを追加する。要素が既存の場合はスコアを更新する。ZRANGE key start stop [WITHSCORES]: ソート済みセットの指定したインデックス範囲の要素を取得する。WITHSCORESオプションでスコアも取得できる。インデックスはスコアの昇順。ZREVRANGE key start stop [WITHSCORES]:ZRANGEの逆で、スコアの降順で取得する。ランキング表示に便利。ZSCORE key member: 指定した要素のスコアを取得する。ZREM key member [member ...]: ソート済みセットから1つ以上の要素を削除する。ZCARD key: ソート済みセットの要素数を取得する。
-
C# (StackExchange.Redis) 例:
“`csharp
// Add scores and members: ZADD highscores score1 member1 score2 member2 …
var scores = new SortedSetEntry[] {
new SortedSetEntry(“Alice”, 1000),
new SortedSetEntry(“Bob”, 1500),
new SortedSetEntry(“Charlie”, 1200)
};
await _database.SortedSetAddAsync(“highscores”, scores);// Get top 3 players (descending order): ZREVRANGE highscores 0 2 WITHSCORES
SortedSetEntry[] topPlayers = await _database.SortedSetRangeByRankWithScoresAsync(“highscores”, 0, 2, Order.Descending);
Console.WriteLine(“Top players:”);
foreach(var player in topPlayers)
{
Console.WriteLine($”{player.Element}: {player.Score}”); // Bob: 1500, Charlie: 1200, Alice: 1000
}// Get Alice’s rank (0-indexed, ascending): ZRANK highscores Alice -> 0
long? aliceRank = await _database.SortedSetRankAsync(“highscores”, “Alice”);
Console.WriteLine($”Alice’s rank (ascending): {aliceRank}”);// Remove Bob: ZREM highscores Bob
await _database.SortedSetRemoveAsync(“highscores”, “Bob”);
“`
これらのデータ構造を理解し、適切に使い分けることで、Azure Redis Cacheは単なるキャッシュとしてだけでなく、様々な機能のバックエンドとしても活用できます。
第7章:キャッシュ戦略と考慮事項
Azure Redis Cacheを効果的に利用するためには、どのようなデータをキャッシュするか、どのようにキャッシュを更新/無効化するかといった「キャッシュ戦略」を適切に設計することが重要です。また、キャッシュ特有の課題(データの整合性、メモリ制限)についても理解しておく必要があります。
7.1 代表的なキャッシュ戦略パターン
-
Cache-Aside (Lazy Loading):
- 仕組み: アプリケーションコードが、まずキャッシュにデータがあるか確認します。キャッシュになければ(キャッシュミス)、データベースからデータを取得し、そのデータをキャッシュに保存してから、アプリケーションに返します。書き込み時は、まずデータベースに書き込み、その後キャッシュのエントリを削除(無効化)または更新します。
- メリット: 実装が比較的シンプル。読み込み時のみキャッシュを更新するため、不要なデータがキャッシュされるのを防げます(よくアクセスされるデータのみがキャッシュされる)。
- デメリット: 初回読み込み時にキャッシュミスが発生し、データベースへのアクセスが必要になるため、初回応答が遅くなる可能性があります。データの整合性を保つために、書き込み後のキャッシュ無効化(または更新)処理が必要です。
- StackExchange.Redisでの実装:
StringGetAsyncでキャッシュをチェックし、StringSetAsyncでキャッシュに書き込み、KeyDeleteAsyncでキャッシュを無効化する。
-
Read-Through:
- 仕組み: アプリケーションは常にキャッシュに問い合わせます。キャッシュがデータを持っていない場合、キャッシュライブラリまたは専用のキャッシュプロバイダが自動的にデータベースからデータを取得し、キャッシュに保存してから、アプリケーションに返します。アプリケーションコードは、キャッシュミス時のデータベースアクセスを意識する必要がありません。
- メリット: アプリケーションコードがシンプルになります。キャッシュミス時の処理をキャッシュプロバイダに任せられます。
- デメリット: 標準のRedisクライアントライブラリでは直接サポートされていません。専用のキャッシュプロバイダライブラリ(.NET Framework時代のEntity Framework Cacheのようなもの)や、カスタム実装が必要です。書き込み戦略と組み合わせる必要があります。
-
Write-Through:
- 仕組み: アプリケーションは常にキャッシュに書き込みます。キャッシュライブラリまたは専用のキャッシュプロバイダが、キャッシュに書き込んだ後、同時にデータベースにもデータを書き込みます。
- メリット: キャッシュとデータベースのデータが常に同期されます(少なくとも書き込み時点では)。
- デメリット: 書き込み処理のレイテンシが、キャッシュとデータベース両方への書き込み時間によって決まります。Read-Throughと同様、専用のライブラリやカスタム実装が必要になる場合があります。
-
Write-Behind (Write-Back):
- 仕組み: アプリケーションはキャッシュにデータを書き込み、キャッシュは書き込み成功を即座に返します。キャッシュは、非同期的に後からまとめて(バッチ処理で)データベースにデータを書き込みます。
- メリット: 書き込みの応答速度が非常に高速になります。データベースへの書き込み負荷を平滑化できます。
- デメリット: キャッシュに書き込まれたデータがデータベースに反映されるまでに遅延が発生します。キャッシュサーバーがクラッシュした場合、データベースに書き込まれていないデータが失われるリスクがあります。実装が複雑になる傾向があります。
初心者の方は、まずCache-Asideパターンから始めるのが最も一般的で理解しやすいでしょう。アプリケーションコード側でキャッシュの存在チェックとデータベースからの読み込み/キャッシュへの書き込みロジックを実装します。
7.2 キャッシュ無効化の重要性
キャッシュ戦略において、データの整合性を維持するために「キャッシュ無効化 (Cache Invalidation)」は非常に重要です。データベースのデータが更新されたのに、キャッシュには古いデータが残っていると、ユーザーは古い情報を参照してしまいます。
主なキャッシュ無効化の方法:
- 有効期限 (Expiration): キャッシュにデータを保存する際に、有効期限(TTL: Time To Live)を設定します。期限が切れたデータはRedisによって自動的に削除されます。次にそのデータが必要になった際はキャッシュミスとなり、データベースから最新のデータが取得されてキャッシュに保存されます。実装が簡単ですが、有効期限が切れるまで古いデータがキャッシュに残る可能性があります。適切な有効期限の設定が重要です(短すぎるとキャッシュヒット率が下がり、長すぎると古いデータが残る期間が長くなる)。
- 明示的な削除: データベースのデータが更新または削除されたタイミングで、アプリケーションコードから対応するキャッシュエントリを明示的に削除します。Cache-Asideパターンでよく使われます。データベースへの書き込み処理が成功した直後にキャッシュを削除することで、キャッシュとデータベースのデータの不整合期間を最小限に抑えられます。
どちらの方法が良いかはシナリオによります。頻繁に更新されるがリアルタイム性はそこまで求められないデータには有効期限、データの鮮度が非常に重要なデータには明示的な削除やWrite-Through/Write-Behindなどが適しています。Cache-Asideパターンでは、書き込み時に明示的な削除を行い、読み込み時に有効期限付きでキャッシュするという組み合わせもよく使われます。
7.3 メモリ制限とエビクション
Azure Redis Cacheインスタンスには、選択したプランとサイズに基づいたメモリ容量の制限があります。キャッシュに保存できるデータ量は、このメモリ容量を超えられません。
メモリが上限に達した場合、Redisは新しいデータを保存するために、既存のデータを削除する必要があります。このプロセスをエビクション (Eviction) と呼びます。エビクションの対象となるデータを決定する方法は、エビクションポリシーによって制御されます。
Azure Redis Cacheで設定可能な主なエビクションポリシー:
- volatile-lru: 有効期限が設定されているキーの中から、最後にアクセスされてから最も時間が経過したキー(LRU: Least Recently Used)を削除する。
- allkeys-lru: 有効期限の有無にかかわらず、全てのキーの中からLRUのキーを削除する。
- volatile-ttl: 有効期限が設定されているキーの中から、有効期限が最も近いキーを削除する。
- volatile-random: 有効期限が設定されているキーの中から、ランダムにキーを削除する。
- allkeys-random: 有効期限の有無にかかわらず、全てのキーの中からランダムにキーを削除する。
- noeviction: メモリ上限に達した場合、新しい書き込み操作を拒否する。
デフォルトポリシーはプランによって異なります(通常は volatile-lru または allkeys-lru)。アプリケーションのデータ特性に合わせて適切なポリシーを選択することが重要です。
推奨事項:
- 有効期限を設定する: ほとんどのキャッシュデータには有効期限を設定することを強く推奨します。これにより、不要になったデータがキャッシュに残り続けるのを防ぎ、エビクションポリシーをより効果的に機能させることができます。
- メモリ使用量を監視する: Azure Monitorを使ってキャッシュのメモリ使用量を常に監視し、上限に近づいていないか確認します。上限に近づいている場合は、キャッシュサイズのスケールアップや、不要なデータのキャッシュを見直す必要があります。
- キャッシュヒット率を監視する: キャッシュが効果的に機能しているかを示す重要な指標です。キャッシュヒット率が低い場合、アプリケーションのキャッシュ戦略(キャッシュすべきデータの選定、有効期限の設定など)を見直す必要があるかもしれません。
エビクションは、キャッシュヒット率の低下やデータ損失につながる可能性があるため、可能な限りメモリ上限に余裕を持たせるように計画しましょう。
第8章:監視とスケーリング
Azure Redis Cacheを運用する上で、キャッシュの健全性やパフォーマンスを監視し、必要に応じてリソースを調整(スケーリング)することは非常に重要です。Azure Monitorは、これらのタスクを実行するための強力なツールを提供します。
8.1 Azure Monitor を使用した監視
Azure Portalでキャッシュインスタンスのページを開き、左側のメニューの「監視」セクションを展開すると、様々な監視機能にアクセスできます。
- 概要 (Overview): キャッシュの基本的な使用状況(CPU、メモリ、接続数、操作数、キャッシュヒット/ミスなど)のグラフがまとめて表示されます。まずここを見て、全体的な傾向を把握します。
- メトリック (Metrics): キャッシュの様々なパフォーマンスカウンター(メトリック)を詳細に確認できます。「メトリック」ブレードを開き、取得したいメトリックを選択してグラフを表示します。
- 主要な監視メトリック:
- CPU 負荷 (CPU Load): キャッシュサーバーのCPU使用率。これが高いと、Redisがリクエストの処理に時間を要している可能性があります。
- メモリ使用量 (Used Memory): キャッシュで使用されているメモリ量。これがキャッシュサイズの物理的な上限に近づくと、エビクションが発生し始めます。
- 接続数 (Client Connections): Redisに接続しているクライアントの数。これが多すぎるとパフォーマンスに影響を与える可能性があります。
- 操作数 (Total Operations): 1秒あたりのRedis操作の総数。スループットを示します。
- キャッシュ ヒット (Cache Hits): 要求されたデータがキャッシュに見つかった回数。
- キャッシュ ミス (Cache Misses): 要求されたデータがキャッシュに見つからなかった回数。
- キャッシュ ヒット率 (Cache Hit Ratio):
Cache Hits / (Cache Hits + Cache Misses)で計算される割合。キャッシュがどれだけ効果的に利用されているかを示します。このメトリックは非常に重要です。高いほど良いです(通常80%以上が目安)。 - 操作レイテンシ (Cache Read/Write Latency): Redisが読み取り/書き込みリクエストに応答するまでの平均時間。これが高いと、キャッシュがボトルネックになっている可能性があります。
- アラートの設定: 各メトリックに対して、閾値を超えた場合に通知を受け取るようにアラートを設定できます。例えば、「Used Memory がキャッシュサイズの90%を超えたら」「Cache Hit Ratio が70%を下回ったら」「CPU Load が80%を継続的に超えたら」といったアラートを設定することで、問題が発生した場合に早期に気づくことができます。
- 主要な監視メトリック:
- 診断と問題解決 (Diagnose and solve problems): パフォーマンス問題、接続問題など、よくある問題のトラブルシューティングガイドやツールが提供されています。
- ログ (Logs): Redisのコマンドレベルの詳細な操作ログなどを収集できます(Premiumプラン以上、診断設定が必要)。
効果的な監視は、パフォーマンス問題を早期に発見し、適切に対応するために不可欠です。特にキャッシュヒット率とメモリ使用量は常に注目しておきましょう。
8.2 スケーリングの種類と実行方法
アプリケーションの負荷が増大し、現在のキャッシュインスタンスではパフォーマンスが不足する場合、スケーリングが必要になります。Azure Redis Cacheには、主に以下のスケーリング方法があります。
- スケールアップ/スケールダウン: 同じプラン内で、より大きいキャッシュサイズ(または小さいサイズ)に変更することです。メモリ容量、帯域幅、CPUコア数が増加(または減少)します。Azure Portalのキャッシュインスタンスページで、左側のメニューの「スケール」を選択して行います。スケーリング中は、キャッシュインスタンスが再起動されるため、一時的に利用できなくなる時間が発生します。
- スケールアウト/スケールイン (Redis Cluster): Premiumプラン以上で利用可能なRedis Cluster機能を有効にしている場合に、シャード(データの分割単位となるノードグループ)の数を増減させることです。これにより、データ容量とスループットを水平方向に拡張できます。Azure Portalの「スケール」ブレードでクラスタリング関連の設定を行います。
- プランのアップグレード/ダウングレード: BasicからStandard、StandardからPremiumのように、より高機能なプランに変更することです。前述の通り、機能だけでなく可用性やパフォーマンス特性も向上します。これも「スケール」ブレードから行えます。通常、プラン変更にはインスタンスの再作成や再起動が必要となり、データ損失のリスクやダウンタイムが発生します。
スケーリングの実行方法 (スケールアップ/ダウン、プラン変更):
- Azure Portalでキャッシュインスタンスのページを開きます。
- 左側のメニューから「スケール」を選択します。
- 表示されたブレードで、希望する「価格レベル」と「キャッシュサイズ」を選択します。
- 「適用」ボタンをクリックします。
警告メッセージが表示されるので内容をよく確認し、同意すればスケーリングが実行されます。通常、数分から数十分かかる場合があります。スケーリング中はキャッシュが利用できなくなる時間が発生するため、メンテナンス時間などを考慮して実行してください。
オートスケール (Premiumプラン以上):
Premiumプラン以上では、CPU負荷などのメトリックに基づいて、キャッシュサイズを自動的にスケールアップ/ダウンさせる「オートスケール」を設定できます。これにより、負荷の変動に柔軟に対応し、コストとパフォーマンスを最適化できます。Azure Portalの「スケール」ブレードの下部にある「手動によるスケーリングまたはオートスケールの構成」から設定できます。
スケーリングはアプリケーションの成長に合わせて適切に行うことが重要です。定期的な監視と合わせて、最適なキャッシュサイズとプランを維持しましょう。
第9章:セキュリティ
Azure Redis Cacheを利用する上で、セキュリティは非常に重要です。外部からの不正アクセスを防ぎ、機密性の高いキャッシュデータを保護するための対策を講じましょう。
- アクセスキー (パスワード) の管理: 前述の通り、アクセスキーはキャッシュへの完全なアクセス権を持つため、厳重に管理し、ソースコードにハードコードしないようにしましょう。Azure Key Vaultなど、安全な場所で管理し、アプリケーションからはそれらのサービスを通じて取得するようにします。定期的なキーの再生成も検討します。
- SSL 接続の強制: アプリケーションとAzure Redis Cache間の通信は、必ずSSL/TLS暗号化を使用して行うようにします。これは、通信経路上のデータの盗聴を防ぐためです。Azure Portalでキャッシュ作成時、または作成後の設定で、SSLポート(6380)を有効にし、非SSLポート(6379)を無効化することを強く推奨します。StackExchange.Redisクライアントでも
ssl=trueオプションを必ず指定してください。 - ファイアウォール規則: パブリックエンドポイントを使用する場合、特定のIPアドレス範囲からの接続のみを許可するようにファイアウォール規則を設定できます。これにより、許可されていないIPアドレスからのアクセスをブロックできます。Azure Portalのキャッシュインスタンスページで、左側のメニューの「ファイアウォール」を選択して設定します。アプリケーションサーバーのパブリックIPアドレスなどを許可リストに追加します。ただし、クライアントIPアドレスが変動する場合(例えば、アプリケーションがPaaSサービスやVNet外にある場合)、ファイアウォールだけでは不十分なことがあります。
- Virtual Network (VNet) 統合 (Premiumプラン以上): キャッシュをAzure Virtual Network内に配置することで、VNet内のリソースからのみプライベートIPアドレス経由でアクセスできるようにします。これにより、インターネットからのアクセスを完全に遮断でき、セキュリティが大幅に向上します。セキュリティが重要な本番環境では、Premiumプラン以上を選択し、VNet統合を検討しましょう。
- Azure Private Link (Premiumプラン以上): VNet統合に加えて、Azure Private Linkを使用することで、キャッシュへのアクセスをAzureバックボーンネットワーク経由に限定し、インターネットを経由させないようにできます。これも高いセキュリティと安定したネットワーク性能を提供します。
- Microsoft Entra ID (旧 Azure AD) 認証 (Premiumプラン以上): アクセスキー(パスワード)の代わりに、Microsoft Entra IDのIDやマネージドIDを使用してキャッシュに認証する仕組みです。パスワード管理の課題を軽減し、Azureリソース間の認証をよりセキュアに行えます。
- Redis コマンドの無効化: セキュリティ上のリスクがある一部のRedisコマンド(例:
KEYS全キー検索、FLUSHALL全データ削除)を無効化できます。Azure Portalの詳細設定やRedis構成設定で指定可能です。
初心者の方は、まず「アクセスキーの安全な管理」と「SSL接続の強制」、「非SSLポートの無効化」を徹底することが重要です。アプリケーションがAzure VNet内で実行されている場合は、Premiumプラン以上を選択してVNet統合を検討しましょう。
第10章:トラブルシューティングのヒント
Azure Redis Cacheを利用する上で、いくつかの一般的な問題に遭遇する可能性があります。ここでは、よくある問題とその診断・解決策のヒントを紹介します。
-
接続エラー:
- 原因: ホスト名の間違い、ポート番号の間違い、無効なアクセスキー、ファイアウォールによるブロック、ネットワーク設定(VNet, Private Linkなど)の問題。
- 診断:
- 接続文字列を確認する:ホスト名、ポート(SSL 6380)、パスワード(アクセスキー)、
ssl=trueオプションが正しいか確認します。 - ファイアウォール設定を確認する:アプリケーションが実行されているIPアドレス(またはIPアドレス範囲)からの接続が許可されているか確認します。
- ネットワーク経路を確認する:アプリケーションとRedis Cacheインスタンス間のネットワーク疎通を確認します。VNet統合やPrivate Linkを使用している場合は、それらの設定が正しいか、DNS解決ができているかなどを確認します。
pingやtelnet(ポート指定) はRedis Cacheではブロックされていることが多いので、代わりにredis-cliやアプリケーションコードから接続を試みます。 - Azure Portalの診断ツールを使用する:「診断と問題解決」ブレードに、接続問題のトラブルシューティングツールがあります。
- 接続文字列を確認する:ホスト名、ポート(SSL 6380)、パスワード(アクセスキー)、
- 解決策: 設定ミスの修正、ファイアウォール規則の追加、ネットワーク構成の見直し。
-
パフォーマンス問題 (高CPU、高メモリ、高レイテンシ):
- 原因: キャッシュサイズ不足、Redis操作の負荷が高い(例:
KEYSコマンドのような高コストな操作、非常に大きな値の読み書き、複雑なLuaスクリプト)、多数の接続、ネットワーク帯域幅の制限。 - 診断:
- Azure Monitorのメトリックを確認する:CPU負荷、メモリ使用量、接続数、操作レイテンシ、キャッシュヒット率などをグラフで確認し、ボトルネックを特定します。
- Slowlog を確認する (Premium以上): 実行に時間がかかったRedisコマンドを確認します。
- StackExchange.Redis のプロファイリング (C#): クライアント側でどのようなコマンドが遅延しているか確認します。
- 解決策:
- スケールアップ: キャッシュサイズを増やして、より多くのCPU、メモリ、ネットワーク帯域幅を確保します。
- スケールアウト (Premium Cluster): データ量やスループット要件が高い場合は、クラスタリングによるスケールアウトを検討します。
- キャッシュ戦略の見直し: 不必要なデータのキャッシュを避ける、キャッシュヒット率を向上させる、高コストなRedis操作を避ける/最適化するなど、アプリケーションコードのキャッシュ利用方法を見直します。
- 接続数の管理:
ConnectionMultiplexerのシングルトン利用を徹底するなど、クライアントからの接続数を適切に管理します。
- 原因: キャッシュサイズ不足、Redis操作の負荷が高い(例:
-
キャッシュエビクション (メモリ不足によるキー削除):
- 原因: キャッシュに保存されているデータ量がキャッシュサイズの上限に達した。
- 診断:
- Azure Monitorの「Used Memory」メトリックがキャッシュサイズの上限に近づいているか確認します。
- 「Evicted Keys」メトリックが増加しているか確認します。
- 解決策:
- スケールアップ: キャッシュサイズを増やします。
- 有効期限の設定: 全てのキャッシュデータに適切な有効期限を設定し、不要なデータがキャッシュに残らないようにします。
- キャッシュするデータの選定: 本当にキャッシュする必要があるデータだけをキャッシュするように見直します。
- エビクションポリシーの確認: 設定されているエビクションポリシーがアプリケーションの要件に合っているか確認します。
-
データ損失:
- 原因: Basicプランの使用(冗長性なし)、Standardプランでのプライマリ/レプリカ両方のノード障害(非常に稀)、Premiumプランでの永続化設定の不備、Write-Behind戦略でのクラッシュ。
- 診断: Redisログ、Azureの診断ログを確認します。
- 解決策:
- 本番環境ではStandard以上のプランを使用し、可用性を確保します。
- データの永続化が必要な場合はPremiumプラン以上を選択し、RDBまたはAOFを適切に設定します。ただし、Redisの永続化はデータベースの代替ではなく、あくまでキャッシュ内容の復旧を助ける機能であり、完全なデータ保全を保証するものではない点に注意が必要です。重要なデータはデータベースに正しく保存する必要があります。
Azure Portalのメトリックやログ、診断ツールを積極的に活用することが、問題解決への近道です。
第11章:発展的なトピック(初心者向けに少しだけ)
この記事は初心者向けですが、Azure Redis Cacheのさらに強力な機能や、関連する概念について少しだけ触れておきます。興味を持ったら、ぜひ公式ドキュメントなどで深く学習してみてください。
- Redis Cluster (Premiumプラン以上): データを複数のノードに分散させ、より大きなデータセットを扱ったり、スループットを向上させたりできる機能です。大規模なアプリケーションでスケーラビリティが求められる場合に重要になります。
- Redis Persistence (Premiumプラン以上): Redisのデータをディスクに保存する機能です(RDBスナップショットまたはAOFログ)。これにより、Redisサーバーが再起動した場合でも、メモリ上のデータを完全に失うことなく復旧できる可能性が高まります。ただし、前述の通りデータベースの代替ではありません。
- Azure Cache for Redis (Enterprise/Enterprise Flash): OSS版Redisではなく、Redis Enterpriseソフトウェアをベースにした上位プランです。モジュールのサポート(RediSearch, RedisTimeSeriesなど)、より高いパフォーマンスや可用性オプションなどが提供されます。特定の高度なユースケースに適しています。
- Pub/Sub (Publish/Subscribe): Redisが持つメッセージングパターンの一つです。特定のチャンネルにメッセージをPublishしたものを、そのチャンネルをSubscribeしているクライアントが受け取れます。リアルタイムのイベント通知やメッセージブローカーとして利用できます。
- Transactions and Scripting (Lua): 複数のRedisコマンドをアトミック(不可分)に実行したり、複雑なロジックをサーバー側で実行したりできます。
これらの機能は、アプリケーションの要件によっては非常に有用ですが、まずは基本的なキャッシュ機能とその使い方をマスターすることから始めましょう。
まとめ:Azure Redis Cacheでアプリケーションを高速化しよう!
この記事では、Azure Redis Cacheの基本的な概念から、Azure Portalを使った作成手順、アプリケーションからの接続方法、基本的な使い方、さらには監視やセキュリティ、トラブルシューティングのヒントまで、初心者向けに詳しく解説しました。
Azure Redis Cacheは、データベースへの負荷を軽減し、アプリケーションの応答速度を劇的に向上させるための強力なツールです。インメモリでデータを保持するRedisの高速性と、Azureが提供するマネージドサービスの利便性が組み合わさることで、サーバー運用に頭を悩ませることなく、アプリケーション開発に集中できます。
まずは、最もシンプルなCache-Asideパターンで、読み込み頻度が高いデータをキャッシュすることから始めてみましょう。慣れてきたら、セッション管理やランキングなど、Redisの多様なデータ構造を活かせる他のシナリオにも挑戦してみてください。
この記事で学んだこと:
- アプリケーションのパフォーマンスボトルネックとなりやすいデータベースアクセスをキャッシュで解決できること。
- Redisは高速なインメモリデータ構造ストアであること。
- Azure Redis CacheはRedisのマネージドサービスであり、運用管理の手間を削減できること。
- Basic, Standard, Premiumなどのプランがあり、要件に合わせて選択すること。
- Azure Portalで簡単にインスタンスを作成できること。
- アプリケーションからの接続にはホスト名とアクセスキーが必要であること。
- .NET (StackExchange.Redis) を使った基本的なキャッシュ操作(Set, Get, Delete)の方法。
- RedisがString, Hash, List, Set, Sorted Setなどの多様なデータ構造をサポートしていること。
- Cache-Asideなどのキャッシュ戦略、キャッシュ無効化、メモリ制限とエビクションについて。
- Azure Monitorを使った監視の重要性と主要なメトリック。
- アプリケーションの負荷に応じたスケーリングの方法。
- アクセスキー管理、SSL接続、ファイアウォール、VNet統合などのセキュリティ対策。
- 一般的なトラブルシューティングのヒント。
Azure Redis Cacheは、あなたのアプリケーションのパフォーマンスを次のレベルに引き上げるための強力な味方となります。ぜひ実際に手を動かして、その速さと便利さを体感してください。
次のステップ:
- Azureアカウント(無料トライアル含む)を取得する。
- この記事を参考に、Azure PortalでBasicまたはStandardプランのAzure Redis Cacheインスタンスを作成してみる。
- 簡単なコンソールアプリケーションやWebアプリケーションを作成し、StackExchange.Redisなどのクライアントライブラリを使って接続し、データのSet/Get/Deleteを試してみる。
- Azure Monitorで作成したキャッシュのメトリック(CPU負荷、メモリ使用量、接続数、操作数)を確認してみる。
この記事が、あなたのAzure Redis Cache導入の助けとなれば幸いです。