この記事では、Redis で電流制限を実装する 3 つの方法を紹介します。一定の参考値があるので、困っている友達が参考になれば幸いです。
[関連する推奨事項: Redis ビデオ チュートリアル ]
高同時実行シナリオがますます増加する中、現在の制限は表示 特に重要です。
もちろん、電流制限を実装する方法はたくさんありますが、Redis には非常に強力な機能がありますので、今回は Redis を使用して比較的簡単に実装できる 3 つの実装方法を実践しました。 Redis は電流制限を実行できるだけでなく、データ統計、近くの人々、その他の機能も実行できます。これについては後で記述する可能性があります。
最初の操作: Redis ベースの setnx 操作
Redis の分散ロックを使用するとき、それが setnx 命令に依存していることは誰もが知っています。 , CAS (比較と交換) 操作中に、指定されたキーに対して有効期限の設定 (expire) も設定されます。電流を制限する主な目的は、単位時間内に N 個の数量のみを持つことです。アクセスできるようにするためのリクエストです。私のコードプログラム。したがって、setnx に依存すると、この機能を簡単に実現できます。
たとえば、10 秒以内に 20 件のリクエストを制限する必要がある場合、setnx の有効期限を 10 に設定することができ、setnx のリクエスト数が 20 に達すると、電流制限の効果が得られます。コードは比較的単純なので省略します。
setnx の具体的な使用法については、私の他のブログ「RedisTemplate での Redis 分散ロックによって引き起こされる一連の問題」を参照してください。
もちろん、このアプローチには多くの欠点があります。 1 ~ 10 秒を数えると、2 ~ 11 秒以内に M 個のリクエストを数えるのは不可能です。N 秒以内に M 個のリクエストを数える必要がある場合、Redis に N 個のキーを保持する必要があり、その他の問題もあります
#2 番目のタイプ: Redis ベースのデータ構造 zset
実際、電流制限に関係する最も重要なことはスライディング ウィンドウです。 10は2-11になります。実際、開始値と終了値は両方とも 1 です。 そして、Redis のリスト データ構造を使用すると、この関数を簡単に実装できます。 リクエストを zset 配列に作成することができ、各リクエストが受信されると、値は一意のままになります。 UUID を使用して生成され、スコアは現在のタイムスタンプで表すことができます。これは、スコアを使用して現在のタイムスタンプ内のリクエストの数を計算できるためです。 zset データ構造は、2 つのタイムスタンプ内のリクエスト数を簡単に取得できるように range メソッドも提供します。 コードは次のとおりです。public Response limitFlow(){ Long currentTime = new Date().getTime(); System.out.println(currentTime); if(redisTemplate.hasKey("limit")) { Integer count = redisTemplate.opsForZSet().rangeByScore("limit", currentTime - intervalTime, currentTime).size(); // intervalTime是限流的时间 System.out.println(count); if (count != null && count > 5) { return Response.ok("每分钟最多只能访问5次"); } } redisTemplate.opsForZSet().add("limit",UUID.randomUUID().toString(),currentTime); return Response.ok("访问成功"); }上記のコードは、スライディング ウィンドウの効果を実現できます。 、N 秒ごとに最大 M リクエストを保証できますが、欠点は、zset のデータ構造がますます大きくなることです。実装方法は比較的簡単です。
3 番目のタイプ: Redis ベースのトークン バケット アルゴリズム
電流制限に関しては、次のことを行う必要があります。トークンバケットアルゴリズムについて言及してください。詳細については、Du Niang の説明を参照してください トークンバケットアルゴリズム
トークンバケットアルゴリズムには入力レートと出力レートが記載されており、出力レートが入力レートよりも大きい場合、トラフィック制限を超えます。 つまり、リクエストにアクセスするたびに、Redis からトークンを取得できます。トークンを取得できれば、制限を超えていないことを意味します。取得できない場合は、結果が返されます。その逆になります。 上記のアイデアに基づいて、Redis の List データ構造を組み合わせることで、このようなコードを簡単に実装できます。これは単純な実装です。 List の leftPop を利用してトークンを取得します。// 输出令牌 public Response limitFlow2(Long id){ Object result = redisTemplate.opsForList().leftPop("limit_list"); if(result == null){ return Response.ok("当前令牌桶中无令牌"); } return Response.ok(articleDescription2); }次に、Java のスケジュールされたタスクに依存して、定期的にトークンをリストに右プッシュします。もちろん、トークンも一意である必要があるため、トークンの生成には引き続き UUID を使用します。要約すると、コードの実装がまったく開始されていません。難しいです。これらの電流制限方法については、上記のコードを AOP またはフィルターに追加して、インターフェイスの現在のフローを制限し、最終的に Web サイトを保護できます。 Redis には実際には他にも多くの用途があり、その役割はキャッシュと分散ロックだけではありません。そのデータ構造は、String、Hash、List、Set、Zset だけではありません。興味のある方は、彼の GeoHash アルゴリズム、BitMap、HLL、Bloom フィルター データ (Redis 4.0 以降に追加され、Docker を使用して redislabs/rebloom を直接インストールできます) の構造をフォローしてください。 プログラミング関連の知識について詳しくは、
プログラミング教育
をご覧ください。 !以上がRedis 電流制限の 3 つの実装方法に関する簡単な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。