「アプリケーションのレスポンスが遅くてDBに負荷が集中している」「セッション管理をインメモリで高速化したい」「Redisの運用・監視を楽にしたい」——バックエンド開発でキャッシュ層の導入は避けて通れない課題です。
結論から言えば、Google Cloud Memorystore for Redisはフルマネージドのインメモリデータストアとして、キャッシュ・セッション管理・Pub/Subの基盤を簡単に構築できます。本記事では、基本概念から本番運用のベストプラクティスまで解説します。
この記事を3秒でまとめると
- MemorystoreはRedis互換のフルマネージドサービスで、パッチ適用・フェイルオーバーが自動
- キャッシュアサイド・ライトスルー・セッションストアなど実践的な設計パターンを解説
- Cloud Run / GKEとのVPC接続でマイクロサービスからの高速アクセスが可能

Memorystore for Redisとは
Memorystore for Redisは、Google Cloudが提供するフルマネージドのRedisサービスです。Redisのインストール・パッチ適用・レプリケーション・フェイルオーバーをすべてGoogleが管理するため、エンジニアはアプリケーション開発に集中できます。
Memorystore vs セルフマネージドRedis
| 比較項目 | Memorystore | セルフマネージドRedis |
|---|---|---|
| セットアップ | 数クリック / コマンド一つ | VM構築、インストール、設定 |
| パッチ適用 | 自動 | 手動 |
| レプリケーション | Standard Tier で自動 | 手動設定 |
| フェイルオーバー | 自動(サブ秒) | 手動 or Sentinel設定 |
| 監視 | Cloud Monitoring統合 | Prometheus等を自前構築 |
| バックアップ | RDB/AOF自動 | 手動設定 |
| 料金 | メモリ量に応じた従量課金 | VM料金 + 運用コスト |
Memorystore のティア
| ティア | 特徴 | 用途 |
|---|---|---|
| Basic | シングルノード、SLA なし | 開発・テスト環境 |
| Standard | リードレプリカ + 自動フェイルオーバー | 本番環境 |
インスタンスの作成
gcloud CLIでの作成
# Standard Tier(本番推奨)
gcloud redis instances create ses-cache \
--size=2 \
--region=asia-northeast1 \
--zone=asia-northeast1-a \
--alternative-zone=asia-northeast1-c \
--tier=standard \
--redis-version=redis_7_2 \
--network=projects/ses-base-prod/global/networks/ses-vpc \
--connect-mode=PRIVATE_SERVICE_ACCESS \
--enable-auth \
--transit-encryption-mode=SERVER_AUTHENTICATION \
--maintenance-window-day=SUNDAY \
--maintenance-window-hour=3 \
--labels=project=ses-base,environment=production
Terraformでの定義
# memorystore.tf
resource "google_redis_instance" "ses_cache" {
name = "ses-cache"
tier = "STANDARD_HA"
memory_size_gb = 2
region = "asia-northeast1"
location_id = "asia-northeast1-a"
alternative_location_id = "asia-northeast1-c"
redis_version = "REDIS_7_2"
authorized_network = google_compute_network.ses_vpc.id
connect_mode = "PRIVATE_SERVICE_ACCESS"
auth_enabled = true
transit_encryption_mode = "SERVER_AUTHENTICATION"
redis_configs = {
"maxmemory-policy" = "allkeys-lru"
"notify-keyspace-events" = "Ex"
"activedefrag" = "yes"
}
maintenance_policy {
weekly_maintenance_window {
day = "SUNDAY"
start_time {
hours = 3
minutes = 0
}
}
}
labels = {
project = "ses-base"
environment = "production"
}
depends_on = [google_service_networking_connection.private_vpc]
}
output "redis_host" {
value = google_redis_instance.ses_cache.host
}
output "redis_port" {
value = google_redis_instance.ses_cache.port
}
キャッシュ設計パターン
パターン1: キャッシュアサイド(Cache-Aside)
最も一般的なキャッシュパターンです。アプリケーションがキャッシュとデータベースの両方を管理します。
// services/cache.service.ts
import Redis from 'ioredis';
const redis = new Redis({
host: process.env.REDIS_HOST,
port: parseInt(process.env.REDIS_PORT || '6379'),
password: process.env.REDIS_AUTH_STRING,
tls: { rejectUnauthorized: false },
retryDelayOnFailover: 100,
maxRetriesPerRequest: 3,
});
// Cache-Aside パターン
export async function getWithCache<T>(
key: string,
fetcher: () => Promise<T>,
ttlSeconds: number = 3600
): Promise<T> {
// 1. キャッシュを確認
const cached = await redis.get(key);
if (cached) {
return JSON.parse(cached) as T;
}
// 2. キャッシュミス → DBから取得
const data = await fetcher();
// 3. キャッシュに保存
await redis.setex(key, ttlSeconds, JSON.stringify(data));
return data;
}
// 使用例
export async function getUserProfile(userId: string) {
return getWithCache(
`user:profile:${userId}`,
() => db.users.findUnique({ where: { id: userId } }),
1800 // 30分キャッシュ
);
}
パターン2: ライトスルー(Write-Through)
書き込み時にキャッシュとデータベースを同時に更新します。データの一貫性が重要な場合に適しています。
// Write-Through パターン
export async function updateUserProfile(
userId: string,
data: Partial<UserProfile>
): Promise<UserProfile> {
// 1. DBを更新
const updated = await db.users.update({
where: { id: userId },
data,
});
// 2. キャッシュも同時に更新
const cacheKey = `user:profile:${userId}`;
await redis.setex(cacheKey, 1800, JSON.stringify(updated));
return updated;
}
パターン3: キャッシュ無効化(Cache Invalidation)
データ更新時にキャッシュを削除し、次のアクセス時に再取得させます。
// Cache Invalidation パターン
export async function invalidateCache(pattern: string): Promise<number> {
const keys = await redis.keys(pattern);
if (keys.length === 0) return 0;
const pipeline = redis.pipeline();
keys.forEach((key) => pipeline.del(key));
await pipeline.exec();
return keys.length;
}
// 使用例:ユーザー関連のキャッシュを一括無効化
await invalidateCache('user:*:123');
セッション管理
Express + connect-redisによるセッションストア
// session.config.ts
import session from 'express-session';
import RedisStore from 'connect-redis';
import Redis from 'ioredis';
const redisClient = new Redis({
host: process.env.REDIS_HOST,
port: parseInt(process.env.REDIS_PORT || '6379'),
password: process.env.REDIS_AUTH_STRING,
tls: { rejectUnauthorized: false },
keyPrefix: 'sess:',
});
const store = new RedisStore({
client: redisClient,
prefix: 'sess:',
ttl: 86400, // 24時間
disableTouch: false,
});
export const sessionMiddleware = session({
store,
secret: process.env.SESSION_SECRET!,
resave: false,
saveUninitialized: false,
name: 'ses.sid',
cookie: {
secure: process.env.NODE_ENV === 'production',
httpOnly: true,
maxAge: 24 * 60 * 60 * 1000, // 24時間
sameSite: 'lax',
domain: '.ses-base.com',
},
});
セッション管理のベストプラクティス
| 項目 | 推奨設定 | 理由 |
|---|---|---|
| TTL | 24時間 | セッション固定攻撃の防止 |
| Cookie属性 | httpOnly, secure, sameSite | XSS/CSRF対策 |
| プレフィックス | sess: | キャッシュデータとの分離 |
| シリアライズ | JSON | デバッグの容易さ |
Cloud Run / GKEとの接続
Cloud RunからMemorystoreへの接続
Cloud RunからMemorystoreにアクセスするには、VPCコネクタまたはDirect VPC Egressを設定します。
# VPCコネクタの作成
gcloud compute networks vpc-access connectors create ses-connector \
--region=asia-northeast1 \
--network=ses-vpc \
--range=10.8.0.0/28 \
--min-instances=2 \
--max-instances=10
# Cloud RunサービスにVPCコネクタを設定
gcloud run deploy ses-api \
--image=asia-northeast1-docker.pkg.dev/ses-base-prod/ses-repo/api-server:latest \
--region=asia-northeast1 \
--vpc-connector=ses-connector \
--vpc-egress=private-ranges-only \
--set-env-vars="REDIS_HOST=$(gcloud redis instances describe ses-cache --region=asia-northeast1 --format='value(host)')"
Direct VPC Egress(推奨)
VPCコネクタの代わりにDirect VPC Egressを使うと、追加のインフラなしでVPC内のリソースにアクセスできます。
gcloud run deploy ses-api \
--image=asia-northeast1-docker.pkg.dev/ses-base-prod/ses-repo/api-server:latest \
--region=asia-northeast1 \
--network=ses-vpc \
--subnet=ses-private-subnet \
--vpc-egress=private-ranges-only
監視とアラート
Cloud Monitoringダッシュボード
Memorystoreは Cloud Monitoring と自動統合されています。以下のメトリクスを監視します。
| メトリクス | 警告閾値 | 緊急閾値 | 対処法 |
|---|---|---|---|
redis.googleapis.com/stats/memory/usage_ratio | 70% | 85% | インスタンスのスケールアップ or データ整理 |
redis.googleapis.com/stats/cpu_utilization | 60% | 80% | コマンド最適化 or スケールアップ |
redis.googleapis.com/stats/connected_clients | 接続数の80% | 接続数の90% | コネクションプール設定の見直し |
redis.googleapis.com/stats/cache_hit_ratio | 80%以下 | 60%以下 | TTL / キャッシュ戦略の見直し |
redis.googleapis.com/stats/evicted_keys | 0超過 | 急増 | メモリ増設 or ポリシー見直し |
アラートポリシーの設定
# メモリ使用率85%超過でアラート
gcloud monitoring policies create \
--display-name="Memorystore Memory Critical" \
--condition-display-name="Redis memory usage > 85%" \
--condition-filter='resource.type="redis_instance" AND metric.type="redis.googleapis.com/stats/memory/usage_ratio"' \
--condition-threshold-value=0.85 \
--condition-threshold-comparison=COMPARISON_GT \
--condition-threshold-duration=300s \
--notification-channels=projects/ses-base-prod/notificationChannels/12345
パフォーマンス最適化
1. パイプラインの活用
複数のコマンドをまとめて送信することで、ネットワークラウンドトリップを削減します。
// パイプラインなし(遅い)
for (const key of keys) {
await redis.get(key); // 各コマンドでラウンドトリップ発生
}
// パイプラインあり(速い)
const pipeline = redis.pipeline();
keys.forEach((key) => pipeline.get(key));
const results = await pipeline.exec();
2. Lua スクリプトによるアトミック操作
// レート制限(スライディングウィンドウ方式)
const rateLimitScript = `
local key = KEYS[1]
local limit = tonumber(ARGV[1])
local window = tonumber(ARGV[2])
local now = tonumber(ARGV[3])
redis.call('ZREMRANGEBYSCORE', key, 0, now - window)
local count = redis.call('ZCARD', key)
if count < limit then
redis.call('ZADD', key, now, now .. '-' .. math.random())
redis.call('EXPIRE', key, window / 1000)
return 1
else
return 0
end
`;
export async function checkRateLimit(
userId: string,
limit: number = 100,
windowMs: number = 60000
): Promise<boolean> {
const result = await redis.eval(
rateLimitScript,
1,
`rate_limit:${userId}`,
limit,
windowMs,
Date.now()
);
return result === 1;
}
3. コネクションプールの適切な設定
const redis = new Redis({
host: process.env.REDIS_HOST,
port: 6379,
password: process.env.REDIS_AUTH_STRING,
tls: { rejectUnauthorized: false },
// コネクション管理
lazyConnect: true,
maxRetriesPerRequest: 3,
retryDelayOnFailover: 100,
enableReadyCheck: true,
// タイムアウト
connectTimeout: 10000,
commandTimeout: 5000,
// 再接続戦略
retryStrategy(times) {
const delay = Math.min(times * 50, 2000);
return delay;
},
});
コスト最適化
Memorystoreの料金体系
| メモリサイズ | Basic Tier(月額) | Standard Tier(月額) |
|---|---|---|
| 1 GB | 約 $35 | 約 $70 |
| 2 GB | 約 $70 | 約 $140 |
| 5 GB | 約 $175 | 約 $350 |
| 10 GB | 約 $350 | 約 $700 |
コスト削減のTips
- 適切なTTL設定: 不要なデータの蓄積を防止
- 圧縮: 大きなJSONデータはlz4等で圧縮してから保存
- データ型の使い分け: HashでフィールドごとにTTLを管理する代わりに、Stringで適切にキーを分割
- Basic Tierの活用: 開発・テスト環境ではBasic Tierを使用
SES案件でのRedis/キャッシュスキル需要
| スキルレベル | 要求される技術 | 想定月額単価 |
|---|---|---|
| 初級 | Redis基本操作、キャッシュ設定 | 50〜60万円 |
| 中級 | キャッシュ設計パターン、セッション管理 | 60〜80万円 |
| 上級 | 分散キャッシュ設計、パフォーマンスチューニング | 80〜100万円 |
まとめ:Memorystoreでキャッシュ基盤を構築しよう
Google Cloud Memorystore for Redisは、アプリケーションのパフォーマンスを劇的に向上させるフルマネージドサービスです。キャッシュアサイド・ライトスルーなどの設計パターンを適切に適用し、Cloud RunやGKEと連携することで、高速かつスケーラブルなバックエンドを構築できます。
SESエンジニアとして、キャッシュ設計のスキルはバックエンド案件での必須能力です。Memorystoreを使いこなして、高パフォーマンスなシステム設計力を身につけましょう。
Google Cloudの基本はGoogle Cloud入門ガイドを、Cloud RunについてはCloud Run + Cloud SQLチュートリアルをご覧ください。データベースはCloud SQL最適化ガイド、セキュリティはIAMセキュリティが参考になります。