編集:更新されたコードで、あなたの方法論はあなたが報告しているものを除いて根本的に欠陥があると私は信じています。
実装方法では、KEYS
を実行する必要があります 本番環境では-これは悪いことです。スケールアウトすると、サーバーの負荷が増大し、不要になります。それに関するドキュメントのすべてのビットが言うように、しないでください keys
を使用する 生産中。キー名に有効期限をエンコードしてもメリットはありません。キー名のその部分を作成タイムスタンプ、またはランダムな番号にした場合でも、何も変わりません。実際、そのビットを削除しても、何も変わりません。
代わりに、より適切なルートは、時間に依存しないキー名を使用することです。有効期限の使用はあなたのためにその機能を処理します。レート制限されたものを「セッション」と呼びましょう。タイムスタンプを除いたキー名は「セッションID」です。 60秒の有効期限を設定すると、61秒のマークでは使用できなくなります。したがって、現在の時刻や有効期限を知らなくても、安全に増分して結果を制限と比較できます。必要なのは、静的キー名とそれに設定された適切な有効期限だけです。
INCR
の場合 存在しないキーの場合、Redisは「1」を返します。これは、キーを作成し、単一のステップ/呼び出しでインクリメントしたことを意味します。したがって、基本的にロジックは次のようになります。
- 「セッション」IDを作成する
- IDを使用してカウンターをインクリメント
- 結果を制限と比較する
- count ==1の場合、有効期限を60秒に設定します
- id count>制限、拒否
ステップ3.1は重要です。カウント1は、これがRedisの新しいキーであり、有効期限を設定することを意味します。それ以外の場合は、有効期限がすでに設定されている必要があります。 3.2で設定すると、カウンターが60秒以上保持されるため、プロセスが中断されます。
これにより、有効期限に基づいて動的なキー名を付ける必要がなくなるため、keys
を使用する必要がなくなります。 レート制限オブジェクトの既存の「セッション」があるかどうかを確認します。また、コードがはるかに単純で予測可能になるだけでなく、Redisへのラウンドトリップが減少します。つまり、Redisの負荷が軽減され、パフォーマンスが向上します。使用しているクライアントライブラリを使用してこれを行う方法については、私はあまり詳しくないため、言えません。ただし、基本的なシーケンスはかなり基本的で単純なので、翻訳可能である必要があります。
ただし、表示していないのは、有効期限が発生していないという主張を裏付けるものです。あなたがしたことは、Redisが実際に通知されて有効期限を設定していることを示すことだけです。あなたの主張を裏付けるために、あなたは鍵が失効していないことを示す必要があります。つまり、有効期限後にキーを取得したことを示す必要があり、有効期限後にカウンターが再作成されて「リセット」されなかったことを意味します。有効期限が発生していることを確認する1つの方法は、キースペース通知を使用することです。これで、キーの有効期限が切れたと言っているRedisを見ることができます。
このプロセスが少し失敗するのは、レート制限のために複数のウィンドウを実行する場合、またはウィンドウがはるかに大きい場合(つまり、10分)の場合です。この場合、並べ替えられたセットは、リクエストのフロントローディングを防ぐためのより適切なオプションです。 -必要に応じて。しかし、あなたの例が書かれているように、上記はうまく機能します。