Flask のキャッシュ戦略(Flask-Caching)

データベースクエリや外部 API 呼び出しの結果をキャッシュすることで、Flask アプリケーションのパフォーマンスを向上できる。Flask-Caching を使ったキャッシュ戦略を解説する。

Flask-Caching のセットアップ

pip install flask-caching
from flask import Flask
from flask_caching import Cache

app = Flask(__name__)
app.config['CACHE_TYPE'] = 'SimpleCache'  # 開発用
app.config['CACHE_DEFAULT_TIMEOUT'] = 300  # 5分

cache = Cache(app)

キャッシュバックエンドの選択

SimpleCacheメモリ内キャッシュ(シングルプロセス向け)
FileSystemCacheファイルシステムに保存
RedisCacheRedis を使用(本番推奨)
MemcachedCacheMemcached を使用

本番環境では Redis を使う。

app.config['CACHE_TYPE'] = 'RedisCache'
app.config['CACHE_REDIS_URL'] = 'redis://localhost:6379/0'

ビューのキャッシュ

@app.route('/posts')
@cache.cached(timeout=60)
def list_posts():
    # このクエリ結果が60秒間キャッシュされる
    posts = Post.query.order_by(Post.created_at.desc()).all()
    return render_template('posts.html', posts=posts)

クエリパラメータを考慮

@app.route('/search')
@cache.cached(timeout=60, query_string=True)
def search():
    q = request.args.get('q')
    # /search?q=flask と /search?q=python で別々にキャッシュ
    return {'results': perform_search(q)}

関数のキャッシュ(メモ化)

@cache.memoize(timeout=300)
def get_user_stats(user_id):
    # 重い計算処理
    return calculate_stats(user_id)

# 呼び出し
stats = get_user_stats(123)  # 初回は計算
stats = get_user_stats(123)  # キャッシュから取得

memoize は引数ごとにキャッシュを作成する。

キャッシュの手動操作

# 設定
cache.set('my_key', 'my_value', timeout=60)

# 取得
value = cache.get('my_key')

# 削除
cache.delete('my_key')

# キーが存在しない場合のみ設定
cache.add('my_key', 'my_value')

キャッシュの無効化

# 特定のビューのキャッシュを削除
cache.delete_memoized(get_user_stats, 123)

# 全キャッシュをクリア
cache.clear()

キャッシュキーのカスタマイズ

def make_cache_key():
    return f'user:{g.user.id}:dashboard'

@app.route('/dashboard')
@cache.cached(timeout=60, key_prefix=make_cache_key)
def dashboard():
    return render_template('dashboard.html')

キャッシュ戦略のパターン

リスト画面はキャッシュ、詳細画面は都度取得
更新頻度の低いマスタデータは長めにキャッシュ
ユーザーごとのデータはキャッシュキーにユーザー ID を含める
書き込み時にキャッシュを無効化

注意点

キャッシュはデータの整合性とのトレードオフである。更新が反映されないと困るデータはキャッシュしないか、短い TTL を設定する。また、キャッシュキーの設計を誤ると、あるユーザーのデータが別ユーザーに見えてしまう危険がある。