Valkey / Redis OSS / Memcached を対象に、設計・接続・運用・セキュリティ・コストの観点で整理したもの。
目次
- エンジンとデプロイ方式の選定
- アーキテクチャ設計
- キャッシュ設計
- クライアント・接続のベストプラクティス
- コマンドの使い方
- セキュリティ
- 監視とアラーム
- バックアップとメンテナンス
- コスト最適化
- Memcached を使う場合の補足
- 本番チェックリスト
1. エンジンとデプロイ方式の選定
エンジン
| エンジン | 向いているケース |
|---|---|
| Valkey(推奨デフォルト) | Redis OSS 互換の OSS フォーク(BSD ライセンス)。Redis OSS より安価で、8.x 以降はメモリ効率も改善。新規構築はまずこれを検討 |
| Redis OSS | 既存資産の都合で Redis OSS に留まる必要がある場合。Valkey へのインプレースアップグレードが可能 |
| Memcached | 単純なキー/値キャッシュのみ、マルチスレッドで水平分散したい、永続化・レプリケーション不要な場合 |
- データ構造(Sorted Set, Stream 等)、レプリケーション、フェイルオーバー、スナップショットが必要なら Valkey / Redis OSS を選ぶ
- Redis OSS 7.x → Valkey はアプリのコード変更なしで移行できるケースがほとんど
Serverless と ノードベース(Self-designed)
| 観点 | Serverless | ノードベース |
|---|---|---|
| キャパシティ管理 | 自動スケール | ノードタイプ・シャード数を自分で設計 |
| 適したワークロード | 負荷変動が大きい、立ち上げ初期、運用負荷を下げたい | 負荷が安定・予測可能、細かいチューニングやコスト最適化をしたい |
| クラスターモード | 常に有効 | 有効/無効を選択 |
| 注意点 | 最大使用量の上限(ECPU/データ量)を設定してコスト暴走を防ぐ | 余裕を持ったサイジングと監視が必須 |
2. アーキテクチャ設計
クラスターモード
- 原則クラスターモード有効で構築する。シャード追加で水平スケールでき、書き込み性能・メモリ容量の上限を引き上げられる
- クラスターモード対応のクライアントライブラリを使う
- 複数キー操作(
MGET、トランザクション、Lua)は同一スロットのキーに限られるため、関連キーにはハッシュタグ{user:123}:profileのように付けて同じスロットに寄せる - ただしハッシュタグの乱用はホットシャードの原因になるので、キーの分散も意識する
高可用性
- Multi-AZ + 自動フェイルオーバーを有効化(本番では必須)
- 各シャードに最低 1 台、可能なら 2 台のレプリカを異なる AZ に配置
- 読み取りをレプリカに振る場合、単一レプリカだけに向けない(障害時に読めなくなる)。2 台以上のレプリカ、またはレプリカ + プライマリに分散する
- レプリカからの読み取りは結果整合である点をアプリ側で許容できるか確認する
- Serverless ではレプリカ用ポート 6380 で読むと同一 AZ のノードから優先的に読み取れ、レイテンシを下げられる
TestFailoverAPI で定期的にフェイルオーバーを試験し、アプリが再接続できることを確認する
サイジング(ノードベース)
- メモリはデータ量だけでなく、レプリケーション・スナップショット・フェイルオーバー時のオーバーヘッドを考慮する
reserved-memory-percentはデフォルトの 25% を基本とする(バックアップや同期時の fork 用バッファ)- 本番は
r系(メモリ最適化)・Graviton(r7gなど)を基本に選定。t系はバースト型のため本番の主要用途には不向き - データ量が大きく、アクセスが一部のキーに偏るなら データ階層化(
r6gd) で SSD を活用してコストを下げる - 複数のシャードに均等に負荷が分散しているか(ホットキー・ホットシャードがないか)を確認する
3. キャッシュ設計
キャッシュ戦略
| 戦略 | 概要 | 注意点 |
|---|---|---|
| Lazy Loading(Cache-Aside) | ミス時に DB から読み込んでキャッシュに書く | 初回はミス。データが古くなる可能性 → TTL で緩和 |
| Write-Through | DB 書き込み時に同時にキャッシュも更新 | 読まれないデータもキャッシュされる → TTL 併用 |
| 併用 | Lazy Loading + Write-Through + TTL | 多くのケースでの推奨パターン |
TTL と追い出し
- 基本的にすべてのキーに TTL を付ける(Write-Through のキーにも付ける)
- 大量のキーが同時に期限切れになるのを避けるため、TTL にランダムなジッターを加える
maxmemory-policyは用途に合わせて設定- 純粋なキャッシュ:
allkeys-lru/allkeys-lfu - TTL 付きキーのみ追い出したい:
volatile-lru/volatile-lfu - データを失いたくない用途(セッション等): 追い出しが起きないようキャパシティを確保し、
Evictionsを監視
- 純粋なキャッシュ:
- サンダリングハード(キャッシュスタンピード)対策: ミス時の DB 再取得をロック(
SET NX)や早期再計算で 1 リクエストに絞る
キーと値の設計
- ビッグキーを避ける(1 つの値が数 MB 以上、要素数が非常に多いコレクション等)。レイテンシ悪化・ネットワーク帯域の圧迫・フェイルオーバー遅延の原因
- 大きいコレクションは分割する。値は必要に応じて圧縮する
- キー名には用途がわかるプレフィックスを付ける(例:
session:,product:)が、長すぎるキー名はメモリを浪費する
4. クライアント・接続のベストプラクティス
- 長寿命の接続を再利用する(コネクションプーリング)。接続確立はキャッシュ側の CPU を消費するため、リクエストごとに接続しない
NewConnectionsが高止まりしていないか監視する(接続の作り直しが多い兆候)- エンドポイントは DNS 名で接続し、IP をハードコードしない(フェイルオーバー時に IP が変わる)
- クラスターモード有効: 設定エンドポイント
- クラスターモード無効: プライマリエンドポイント / リーダーエンドポイント
- DNS の TTL を尊重するようクライアント(特に JVM の DNS キャッシュ)を設定する
- 接続タイムアウト・コマンドタイムアウトを適切に設定し、無期限に待たない
- リトライは指数バックオフ + ジッターで行い、障害時にリトライが集中しないようにする
- パイプラインを使って往復回数を減らす(大量の小さいコマンドを送る場合)
- クラスター構成の変更(シャード追加、フェイルオーバー)時に
MOVED/ASKを正しく処理できるクライアントを使う - AWS が推奨する GLIDE(Valkey GLIDE)など、クラスター・フェイルオーバー対応が成熟したクライアントを検討する
5. コマンドの使い方
KEYSは本番で使わない →SCANを使うSMEMBERS,HGETALL,LRANGE 0 -1など大きなコレクションを一括取得するコマンドは避け、SSCAN/HSCANなどで分割取得する- 大きなキーの削除は
DELではなくUNLINK(非同期削除)を使う FLUSHALL/FLUSHDBはASYNCオプションを付ける- Lua スクリプト
- 長時間実行するスクリプトは避ける(実行中は他のコマンドがブロックされる)
- 使用するキーは必ず
KEYS引数で事前に宣言し、すべて同じスロットに属するようにする
- Pub/Sub: 高スループットなら Sharded Pub/Sub(
SPUBLISH/SSUBSCRIBE)を使う。従来の Pub/Sub はクラスター全ノードにブロードキャストされEngineCPUUtilizationが上がる - スローログ(
SLOWLOG)を CloudWatch Logs / Kinesis Data Firehose に配信し、遅いコマンドを継続的に把握する
6. セキュリティ
- VPC 内に配置し、プライベートサブネットのみを使う。パブリックアクセスはさせない
- セキュリティグループでアクセス元をアプリケーションのセキュリティグループのみに限定する
- 転送中の暗号化(TLS)を有効化
- 保存時の暗号化を有効化(必要に応じてカスタマー管理の KMS キーを使用)
- 認証
- Valkey / Redis OSS 6 以降は RBAC(ユーザーグループ + ACL) を使い、アプリごとに最小権限のユーザーを作る
- IAM 認証を使うとパスワード管理が不要になる
- AUTH トークン/パスワードを使う場合は Secrets Manager で管理し、ローテーションする
CONFIG,FLUSHALL,KEYSなどの危険なコマンドはアプリ用ユーザーの ACL で禁止する- CloudTrail で ElastiCache API の操作履歴を記録する
7. 監視とアラーム
主要な CloudWatch メトリクス
| メトリクス | 見るポイント | アラームの目安 |
|---|---|---|
EngineCPUUtilization | Valkey/Redis のメインスレッドの CPU | 継続的に 80〜90% 超 |
CPUUtilization | ホスト全体の CPU(小さいノードで重要) | vCPU 数に応じて設定 |
DatabaseMemoryUsagePercentage | メモリ使用率 | 80% 超で警告 |
Evictions | 追い出し発生数 | 想定外の増加(データを失いたくない用途では 0 を期待) |
CurrConnections / NewConnections | 接続数・新規接続数 | 急増・高止まり |
ReplicationLag | レプリカの遅延 | 秒単位の継続的な遅延 |
SwapUsage | スワップ使用量 | 50 MB 超 |
CacheHitRate(または Hits/Misses) | キャッシュの効果 | 想定より低い場合は TTL・キー設計を見直す |
NetworkBytesIn/Out, NetworkBandwidthAllowanceExceeded 系 | ネットワーク帯域の上限 | 超過カウントが 0 より大きい |
Serverless: ElastiCacheProcessingUnits, BytesUsedForCache | 使用量 | 上限設定値に近づいたら |
- ElastiCache のイベント(フェイルオーバー、メンテナンス等)を SNS / EventBridge で通知する
- エンジンログ・スローログを有効化し、ログを集約する
8. バックアップとメンテナンス
- 自動バックアップを有効化し、保持期間を要件に合わせて設定する(純粋なキャッシュで再生成可能なら不要な場合もある)
- バックアップはプライマリへの負荷を避けるためレプリカから取得されるように構成する。メモリに余裕がないと fork 時に性能劣化・スワップが起こる
- メンテナンスウィンドウとバックアップウィンドウを低トラフィック時間帯に設定し、両者を重ねない
- サービス更新(セキュリティパッチ等)は期限前に計画的に適用する
- スケーリングはオンラインリサイズ(シャード追加/削除、ノードタイプ変更)を使い、低負荷時に実施する
- エンジンのメジャーバージョンアップは、まずステージング環境で互換性と性能を検証する
9. コスト最適化
- Redis OSS から Valkey へ移行すると料金が下がる(Serverless・ノードベースとも Valkey の方が安価)
- Graviton ベースのノード(
r7g,m7g等)を選ぶ - 安定したワークロードにはリザーブドノードを購入する
- 使用率が低いクラスターは縮小し、データ量が大きい場合はデータ階層化を検討する
- Serverless は最大使用量の上限を設定して想定外の課金を防ぐ
- 開発・検証環境はレプリカなし・小さいノードにする
10. Memcached を使う場合の補足
- データはノード間で分散されるだけでレプリケーションされない。ノード障害でデータが消える前提で設計する
- Auto Discovery 対応クライアントを使い、ノード追加/削除に自動追従する
- ノード追加時のキー再配置を最小にするため、コンシステントハッシュを使う
- ノードは複数 AZ に分散配置する
11. 本番チェックリスト
- エンジンは Valkey を第一候補として検討した
- Serverless / ノードベースの選定理由が明確
- クラスターモード有効(ノードベースの場合)
- Multi-AZ + 自動フェイルオーバー有効、シャードごとに 1 台以上のレプリカ
-
reserved-memory-percentとmaxmemory-policyを用途に合わせて設定 - すべてのキーに TTL(+ ジッター)を設定
- コネクションプーリング、タイムアウト、指数バックオフ付きリトライを実装
- DNS エンドポイントで接続し、IP をハードコードしていない
-
KEYSなど重いコマンドを使っていない、ビッグキーがない - 高スループットの Pub/Sub は Sharded Pub/Sub
- VPC・セキュリティグループで閉域化、転送中/保存時の暗号化有効
- RBAC または IAM 認証で最小権限
- 主要メトリクスに CloudWatch アラーム、イベント通知を設定
- スローログ・エンジンログを配信
- バックアップ・メンテナンスウィンドウを設定、フェイルオーバーテスト済み
- リザーブドノード・Graviton・データ階層化などコスト最適化を検討