『API Gateway 任せ』から『アプリ層でのきめ細かい制限』へ
API レート制限は基本概念は API Gateway 側で扱えますが、アプリ層での実装が必要な場面もあります。本記事では編集部の視点で、Redis を活かした実装パターンを公開情報をもとに整理します。APIレート制限実装ガイド もご参考に。
なぜアプリ層が必要か
(1) 細かいビジネスロジック制限:ユーザー単位/プラン単位。(2) 動的調整:プロモコードで一時緩和。(3) 使用量計測連動:billing と統合。(4) Gateway の制限機能の限界。(5) マルチクラウド対応:場所を問わない。
Token Bucket の Redis Lua 実装
(1) atomic 性:Lua スクリプトで保証。(2) 状態:last_refill_time, tokens を Redis Hash で。(3) refill ロジック:(now - last) * refill_rate。(4) consume チェック:tokens >= cost。(5) 戻り値:成功/失敗+残量。EVAL コマンドで実行します。Redis 実践 もご参考に。
Sliding Window Log
(1) Sorted Setでタイムスタンプ管理。(2) ZADDで追加。(3) ZREMRANGEBYSCOREで古いものを削除。(4) ZCOUNTで count。(5) 欠点:メモリ消費(高頻度ユーザーで増)。
Sliding Window Counter
(1) 現在 window + 1つ前 windowのカウンタ。(2) 1つ前への重み:(window_size - elapsed) / window_size。(3) メモリ効率:Sorted Set 不要。(4) 精度:Sliding Window Log より低いが現実的。(5) 実用的な選択。
分散環境の考慮
(1) Redis Cluster:キー分散。(2) Lua script の slot:同一 hash tag 必要。(3) Read replica の遅延:書込みは master。(4) Lua script のサイズ上限。(5) SCRIPT LOAD + EVALSHAでキャッシュ。
運用上の注意
(1) Redis 障害時のフォールバック。(2) レート制限ヒット率のメトリクス。(3) 429 + Retry-After標準応答。(4) X-RateLimit-*ヘッダ送信。(5) テストでの検証:本番に近い負荷で。Observability 実践 も合わせて。
失敗しがちなパターン
(1) 非アトミックな実装:競合で誤判定。(2) Redis 障害でサービス停止:fail-open vs fail-closed。(3) キーカーディナリティ爆発:メモリ大量消費。(4> 制限値が静的:動的調整できない。(5) 本番でしか発覚。対策は、(1)Lua atomic、(2)フォールバック設計、(3)TTL設定、(4)動的設定、(5)k6 等で負荷試験、です。