Memorystore for Redisを用いてセッション管理を行う
はじめに
こんにちは。
クラウド事業本部コンサルティング部の渡邉です。
Webアプリケーションを運用する際に、「セッション管理」について考える場面があると思います。特に Cloud Run のようなサーバーレス環境では、インスタンスがスケールイン/アウトするため、ローカルメモリにセッションを保持する方式では正しくセッション管理を行えません。
そこで今回は、Google Cloud のフルマネージドなインメモリデータストアである Memorystore for Redis を使い、Cloud Run 上の Web アプリケーションでセッション管理を行う方法について紹介します。
セッション管理とは
改めて、Webアプリケーションにおける セッション管理 とは、ユーザーごとの一時的な状態(ログイン状態、カートの中身、フォームの入力途中データなど)をサーバー側で保持する仕組みです。
HTTP はステートレスなプロトコルであるため、リクエスト間で状態を保持するにはセッション管理の仕組みが必要です。一般的には、以下のような流れで動作します。
セッションストアの選択肢
セッションデータの保存先としては、いくつかの選択肢があります。
| 保存先 | メリット | デメリット |
|---|---|---|
| アプリのローカルメモリ | 最もシンプル | スケールアウト時にセッションが失われる |
| データベース(Cloud SQL など) | 永続性が高い | レイテンシが大きい |
| インメモリストア(Redis など) | 低レイテンシ・高スループット | データの永続性に注意が必要 |
Cloud Run のようにインスタンスが動的にスケールする環境では、外部のセッションストアを使うことが推奨されます。中でも Redis は、サブミリ秒のレイテンシとキーの有効期限(TTL)機能を備えており、セッション管理に適したデータストアとして知られています。
Memorystore for Redis とは
Memorystore for Redis は、Google Cloud が提供する Redis のフルマネージドサービスです。Redis のプロトコルに完全互換で、既存の Redis クライアントライブラリをそのまま利用できます。
主な特徴は以下のとおりです。
| 項目 | 内容 |
|---|---|
| マネージド | パッチ適用、障害検知、自動フェイルオーバーを自動化 |
| サービスティア | Basic Tier(単一ノード)/ Standard Tier(レプリケーション・自動フェイルオーバー) |
| 最大容量 | 300 GB |
| ネットワーク帯域 | 最大 16 Gbps |
| サポートバージョン | Redis 7.2, 7.0, 6.x |
| セキュリティ | プライベート IP でのアクセス、IAM によるアクセス制御、転送中の暗号化 |
| 監視 | Cloud Monitoring / Cloud Logging と統合 |
| 課金 | プロビジョニングした容量(GB)に対する時間課金 |
Memorystore for Redisを構築・運用する上で、サービスティアについて理解することが大切になります。Basic Tier はレプリケーションのないスタンドアロン構成です。キャッシュ用途で一時的なデータを扱う場合に適しています。Standard Tier はゾーン間レプリケーションと自動フェイルオーバーを備え、99.9% の SLA を提供します。セッション管理で高可用性が必要な場合は Standard Tier を検討してください。
Cloud Run から Memorystore に接続するアーキテクチャ
Cloud Run から Memorystore for Redis に接続するには、VPC ネットワーク経由でのアクセスが必要です。Memorystore for Redis はプライベート IP のみで公開されるため、Cloud Run サービスが同じ VPC ネットワークにアクセスできる必要があります。
接続方式として Direct VPC egress が推奨されています。Direct VPC egress は、Serverless VPC Access コネクタを使う方式と比較して、低レイテンシ・高スループット・低コストというメリットがあります。Direct VPC egress を使用する場合、サブネットは /26 以上のサイズが必要になることに注意が必要です。本記事では /24 を使用しています。
実際に試してみる
ここからは、Cloud Run 上の Python(Flask)アプリケーションから Memorystore for Redis に接続し、セッション管理を行う手順を紹介します。
前提条件
- Google Cloud プロジェクトが作成済みであること
gcloudCLI がインストール・認証済みであること- 以下の API が有効化されていること
- Redis API(
redis.googleapis.com) - Cloud Run API(
run.googleapis.com) - Artifact Registry API(
artifactregistry.googleapis.com) - Cloud Build API(
cloudbuild.googleapis.com) - Compute Engine API(
compute.googleapis.com)
- Redis API(
環境変数の設定
以降のコマンドで使用する変数を設定します。
export PROJECT_ID=YOUR_PROJECT_ID
export REGION=asia-northeast1
export NETWORK=session-network
export SUBNET=session-subnet
gcloud config set project $PROJECT_ID
ステップ 1: API の有効化
今回の検証で必要な各種サービスに対するAPIを有効化します。
gcloud services enable \
redis.googleapis.com \
run.googleapis.com \
artifactregistry.googleapis.com \
cloudbuild.googleapis.com \
compute.googleapis.com \
--project=$PROJECT_ID
Operation "operations/acf.p2-XXXXXXXXXXXX-a7e2db03-f800-4f7a-bec2-547b7ea53a74" finished successfully.
ステップ 2: VPC ネットワークとサブネットの作成
Memorystore for Redis はプライベート IP でのみアクセス可能なため、専用の VPC ネットワークとサブネットを作成します。
# VPC ネットワークの作成(カスタムモード)
gcloud compute networks create $NETWORK \
--subnet-mode=custom \
--project=$PROJECT_ID
# サブネットの作成
gcloud compute networks subnets create $SUBNET \
--network=$NETWORK \
--region=$REGION \
--range=10.0.0.0/24 \
--project=$PROJECT_ID
Created [https://www.googleapis.com/compute/v1/projects/YOUR_PROJECT_ID/global/networks/session-network].
NAME SUBNET_MODE BGP_ROUTING_MODE IPV4_RANGE GATEWAY_IPV4 INTERNAL_IPV6_RANGE
session-network CUSTOM REGIONAL
Created [https://www.googleapis.com/compute/v1/projects/YOUR_PROJECT_ID/regions/asia-northeast1/subnetworks/session-subnet].
NAME REGION NETWORK RANGE STACK_TYPE IPV6_ACCESS_TYPE INTERNAL_IPV6_PREFIX EXTERNAL_IPV6_PREFIX
session-subnet asia-northeast1 session-network 10.0.0.0/24 IPV4_ONLY

構築したVPCとサブネット
ステップ 3: Memorystore for Redis インスタンスの作成
検証用に Basic Tier で 1 GB のインスタンスを作成します。--network で作成した VPC ネットワークを指定し、接続モードには DIRECT_PEERING を使用します。
gcloud redis instances create session-store \
--size=1 \
--region=$REGION \
--zone=asia-northeast1-a \
--network=$NETWORK \
--connect-mode=DIRECT_PEERING \
--redis-version=redis_7_2 \
--project=$PROJECT_ID
作成が完了したら、IP アドレスとポート番号を確認します。
gcloud redis instances describe session-store \
--region=$REGION \
--project=$PROJECT_ID \
--format="value(host,port)"
10.255.217.203 6379

ステップ 4: サンプルアプリケーションの作成
セッション管理を行う Flask アプリケーションを作成します。redis-py と Flask を使い、Redis をセッションストアとして利用します。
requirements.txt
Flask==3.1.3
gunicorn==23.0.0
redis==6.0.0
app.py
import os
import uuid
import json
from datetime import datetime
from flask import Flask, request, make_response
import redis
app = Flask(__name__)
redis_host = os.environ.get("REDISHOST", "localhost")
redis_port = int(os.environ.get("REDISPORT", 6379))
redis_client = redis.StrictRedis(host=redis_host, port=redis_port, decode_responses=True)
SESSION_TTL = 3600 # セッションの有効期限: 1時間
def get_or_create_session(session_id):
"""既存のセッションを取得、または新規作成する"""
if session_id:
session_data = redis_client.get(f"session:{session_id}")
if session_data:
redis_client.expire(f"session:{session_id}", SESSION_TTL)
return session_id, json.loads(session_data)
new_session_id = str(uuid.uuid4())
session_data = {"created_at": datetime.now().isoformat(), "visit_count": 0}
redis_client.setex(f"session:{new_session_id}", SESSION_TTL, json.dumps(session_data))
return new_session_id, session_data
@app.route("/")
def index():
session_id = request.cookies.get("session_id")
session_id, session_data = get_or_create_session(session_id)
session_data["visit_count"] += 1
session_data["last_visited"] = datetime.now().isoformat()
redis_client.setex(f"session:{session_id}", SESSION_TTL, json.dumps(session_data))
response = make_response(
f"Session ID: {session_id}\n"
f"Visit Count: {session_data['visit_count']}\n"
f"Created At: {session_data['created_at']}\n"
f"Last Visited: {session_data['last_visited']}\n"
)
response.set_cookie("session_id", session_id, max_age=SESSION_TTL, httponly=True)
return response
@app.route("/session/delete")
def delete_session():
session_id = request.cookies.get("session_id")
if session_id:
redis_client.delete(f"session:{session_id}")
response = make_response("Session deleted.\n")
response.delete_cookie("session_id")
return response
if __name__ == "__main__":
app.run(host="0.0.0.0", port=8080, debug=True)
このアプリケーションでは以下のポイントを実装しています。
GET /: セッションの作成・更新。訪問回数をカウントするGET /session/delete: セッションの削除setexコマンドで TTL(有効期限)を設定し、一定期間アクセスがないセッションを自動削除- アクセスのたびに
expireで TTL をリセットし、アクティブなセッションを延長
Dockerfile
FROM python:3.12-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY app.py .
CMD ["gunicorn", "--bind", "0.0.0.0:8080", "app:app"]
ステップ 5: コンテナイメージのビルドとプッシュ
Artifact Registry にリポジトリを作成し、Cloud Build でコンテナイメージをビルドします。
# Artifact Registry リポジトリの作成
gcloud artifacts repositories create session-app \
--location=$REGION \
--repository-format=docker \
--project=$PROJECT_ID
Create request issued for: [session-app]
Waiting for operation [projects/YOUR_PROJECT_ID/locations/asia-northeast1/operations/f23a24b5-d298-487c-94d0-38e5806ea8bc] to complete...done.
Created repository [session-app].
# Cloud Build でイメージをビルド
gcloud builds submit \
--pack image=$REGION-docker.pkg.dev/$PROJECT_ID/session-app/session-app:v1 \
--project=$PROJECT_ID
DONE
-------------------------------------------------------------------------------------------------------------------------------------
ID CREATE_TIME DURATION SOURCE IMAGES STATUS
d4318002-04d6-4deb-b0aa-afc7a8ede6bc 2026-08-09T19:59:21+00:00 1M33S gs://YOUR_PROJECT_ID_cloudbuild/source/1786305557.062782-def279db5f6a4195bb3069489e3c126e.tgz asia-northeast1-docker.pkg.dev/YOUR_PROJECT_ID/session-app/session-app:v1 SUCCESS

ステップ 6: Cloud Run へのデプロイ
Memorystore の IP アドレスを取得し、Cloud Run サービスをデプロイします。Direct VPC egress を使用して VPC ネットワークに接続します。
# Memorystore の IP アドレスを取得
REDIS_IP=$(gcloud redis instances describe session-store \
--region=$REGION \
--project=$PROJECT_ID \
--format="value(host)")
REDIS_PORT=$(gcloud redis instances describe session-store \
--region=$REGION \
--project=$PROJECT_ID \
--format="value(port)")
# Cloud Run へデプロイ
gcloud run deploy session-app \
--image=$REGION-docker.pkg.dev/$PROJECT_ID/session-app/session-app:v1 \
--region=$REGION \
--network=$NETWORK \
--subnet=$SUBNET \
--vpc-egress=private-ranges-only \
--set-env-vars=REDISHOST=$REDIS_IP,REDISPORT=$REDIS_PORT \
--allow-unauthenticated \
--project=$PROJECT_ID
Deploying container to Cloud Run service [session-app] in project [YOUR_PROJECT_ID] region [asia-northeast1]
✓ Deploying new service... Done.
✓ Creating Revision...
✓ Routing traffic...
✓ Setting IAM Policy...
Done.
Service [session-app] revision [session-app-00001-5qh] has been deployed and is serving 100 percent of traffic.
Service URL: https://session-app-XXXXXXXXXXXX.asia-northeast1.run.app

ステップ 7: 動作確認
デプロイされた Cloud Run サービスの URL を取得し、動作を確認します。
# サービス URL の取得
SERVICE_URL=$(gcloud run services describe session-app \
--region=$REGION \
--project=$PROJECT_ID \
--format="value(status.url)")
$ curl -c cookies.txt $SERVICE_URL
Session ID: 49accccb-5450-4293-b8b0-beb9c1d09d6e
Visit Count: 1
Created At: 2026-08-09T20:03:45.781155
Last Visited: 2026-08-09T20:03:45.784427
$ curl -b cookies.txt -c cookies.txt $SERVICE_URL
Session ID: 49accccb-5450-4293-b8b0-beb9c1d09d6e
Visit Count: 2
Created At: 2026-08-09T20:03:45.781155
Last Visited: 2026-08-09T20:03:52.656581
$ curl -b cookies.txt -c cookies.txt $SERVICE_URL
Session ID: 49accccb-5450-4293-b8b0-beb9c1d09d6e
Visit Count: 3
Created At: 2026-08-09T20:03:45.781155
Last Visited: 2026-08-09T20:03:59.438163
$ curl -b cookies.txt -c cookies.txt $SERVICE_URL/session/delete
Session deleted.
1回目のアクセスでは Visit Count: 1 が返り、2回目以降はカウントが増加していくことが確認できます。
ブラウザからアクセスする場合、サーバーが Set-Cookie ヘッダーを返すと、ブラウザが自動的に Cookie を保存し、以降の同一ドメインへのリクエストに Cookie: session_id=xxx を付与します。開発者が明示的に Cookie を扱うコードを書く必要はありません。
一方、curl はブラウザではないため Cookie を自動管理しません。上記のコマンドでは -c cookies.txt(Cookie の保存)と -b cookies.txt(Cookie の送信)を明示的に指定することで、ブラウザと同等のセッション維持を再現しています。
以下のシーケンス図は、複数回アクセスした際のセッション管理の流れを示しています。
まとめ
本記事では、Memorystore for Redis と Cloud Run を使って Web アプリケーションのセッション管理を行う方法を紹介しました。
Memorystore for Redis は、セッション管理に最適なフルマネージドのインメモリデータストアです。サブミリ秒のレイテンシでデータにアクセスでき、Redis の TTL 機能を使うことで有効期限付きのセッション管理を簡潔に実装できます。パッチ適用や監視などの運用タスクが自動化されているため、アプリケーション開発に集中できる点も大きなメリットです。
Cloud Run から Memorystore への接続は、Direct VPC egress を使うことでシンプルに実現できます。従来の Serverless VPC Access コネクタと比較して、コネクタインスタンスが不要なため低コストであり、レイテンシやスループットの面でも優位です。なお、Memorystore for Redis はプライベート IP でのみアクセス可能なため、VPC ネットワークの設定は必須となります。
今回は検証用に Basic Tier を使用しましたが、本番環境では自動フェイルオーバーとゾーン間レプリケーションを備えた Standard Tier の利用を推奨します。セッションデータの喪失がユーザー体験に影響する場合は、Standard Tier により 99.9% の SLA が保証されるため、安心して運用できます。
この記事が誰かの助けになれば幸いです。
以上、クラウド事業本部コンサルティング部の渡邉でした!




