Redisのトークンバケットリストリクタ

まず、シーン記述

サーバプロセスの開発・インタフェースでは、クライアント・インターフェースの乱用を防ぐために、サーバリソースの保護は、一般に、我々は、サーバー上のさまざまなインターフェイスのための呼び出しの数が制限されます。例えば、1分として、例えば、サーバインターフェイスが上限値(上限)を超えることはできません呼び出し時間の期間(インターバル)で、回数ユーザについて、100倍。ユーザの数が呼び出しインターフェイスの上限を超えた場合、それはユーザの要求を指示することを拒否し、エラーメッセージを返します。
フロー制御戦略インターフェースサービス:転換、降格、電流制限。この記事では、サービス・インターフェースへの同時アクセスの頻度と量を減少させるが、下限トラフィックポリシーについて説明したが、高可用性サービス・インターフェースとビジネスアプリケーションシステムの交換です。

第二に、一般的な制限アルゴリズム

1、トークンバケットアルゴリズム
水が直接アセンブリを通ってオーバフローリーキーバケット(漏出バケット)アルゴリズムは、(非常にシンプルなアイデア、最初のバケットに排出する水(リクエスト)、一定速度(インターフェースに応答速度)でバケット水、流入速度でありますインターフェースアクセス頻度が応答速度を超える)、及び、要求を拒否し、伝送速度がリーキーバケットアルゴリズムは、以下の概略のデータに制限を課すことができることがわかります。

 

   

 
 


2つの変数が見ることができますがありますが、それは、トラフィックのサポートが急激に増加し、他のバケットの脆弱性(率)の大きさであるとき、水(バースト)を保存することができますどのくらい、バレルの大きさです。
リーキーバケットパラメータの漏洩速度は固定されているので、その結果、ネットワークリソースの競合が存在しない場合であっても(輻輳が発生していない)、トークンバケットアルゴリズムは、ポート速度にストリームバースト(バースト)しません。このように、投影用のトークンバケットアルゴリズムの存在を髪の流れ特性は非効率的です。

2、トークンバケットアルゴリズム
トークンバケットアルゴリズム(トークンバケット)と同様の効果リーキーバケットアルゴリズムが、反対方向に、より容易に理解される。以上の時間、システムは、定数1 / QPS間隔(QPS = 100なら、となりますインターバルバケットでは10ms)がトークン(バケツがいっぱいになった場合は、水道水で一定の増加が)、そこにある、リークを想像し、逆抜け穴追加され、新しい要求に結合されていない来て、私たちは、それぞれのトークンを取り、もしません。トークンは、彼らがブロックされたり、サービス拒否撮像することができます。

 

 
 

別の利点は、容易に速度を変更することができるトークンバケットである。率、バケットにトークンの速度を増加させる要求を増やす必要が一旦一般タイミング(例えば100ミリ秒)トークンの特定の数にタブを増加、リアルタイムの計算アルゴリズムのいくつかの亜種の数は、トークンを増やす必要があります。

Redisのを実装PHP +トークンバケットアルゴリズムに基づいて第三に、

<?php
namespace Api\Lib; /** * 限流控制 */ class RateLimit { private $minNum = 60; //单个用户每分访问数 private $dayNum = 10000; //单个用户每天总的访问量 public function minLimit($uid) { $minNumKey = $uid . '_minNum'; $dayNumKey = $uid . '_dayNum'; $resMin = $this->getRedis($minNumKey, $this->minNum, 60); $resDay = $this->getRedis($minNumKey, $this->minNum, 86400); if (!$resMin['status'] || !$resDay['status']) { exit($resMin['msg'] . $resDay['msg']); } } public function getRedis($key, $initNum, $expire) { $nowtime = time(); $result = ['status' => true, 'msg' => '']; $redisObj = $this->di->get('redis'); $redis->watch($key); $limitVal = $redis->get($key); if ($limitVal) { $limitVal = json_decode($limitVal, true); $newNum = min($initNum, ($limitVal['num'] - 1) + (($initNum / $expire) * ($nowtime - $limitVal['time']))); if ($newNum > 0) { $redisVal = json_encode(['num' => $newNum, 'time' => time()]); } else { return ['status' => false, 'msg' => '当前时刻令牌消耗完!']; } } else { $redisVal = json_encode(['num' => $initNum, 'time' => time()]); } $redis->multi(); $redis->set($key, $redisVal); $rob_result = $redis->exec(); if (!$rob_result) { $result = ['status' => false, 'msg' => '访问频次过多!']; } return $result; } } 

コードポイント:
1:まず、ルールが定義
分ごとに単一のユーザ訪問($ minNum)、一日あたりの訪問の総数($ dayNum)の単一のユーザに、異なるルールは、全セッション数等をインターフェース。
2:速度計算
時間、速度=アクセス数の最小単位に第2のサンプルコードを/時間(期限切れinitNum $ / $)
3:計算補数トークン各アクセス後に
、すなわち、最終アクセス時刻取得トークン缶がトークン初期化の数の合計数よりも多くないの後に定期預金現在の時刻と最終アクセス時間差を計算するためのトークン時間が補完される割合ニーズのトークンの数を乗じて、注意を払うには、トークンを追加します補足するために最小数と初期化の数が優先する。
4:プログラムの流れ
に初めてアクセストークンの初期化数($ minNum)、預金は店舗数あなたが追加する必要がある次の時間を計算するために、現在のタイムスタンプトークンをRedisのながら。残りのトークン、番号の2番目の訪問数を取得し、このトークンを追加する必要があります追加し、トークンの数は、現在のアクセスは、使用後のアクセスまたはアクセス不能にトークンも有効ですが、どのように> 0の後に追加します。最初のサプリメントは、その後でこの概念があるので、最後の速度がゼロにトークン残りますが、これはトークン> 1、これはまだアクセスすることができます追加する必要がある場合、トークントークン> 0の理由は、あるかどうかを判断します。
5:並行処理のため
のRedisを使用して楽観的ロック機構

四、Redisの楽観的ロックの紹介

取引のためのRedisのサポートは比較的簡単です。Redisのは、唯一の他の事項は挿入されません間でクライアントを開始トランザクションコマンドは、実行することができます保証することができます。それは上記の操作を行うことは非常に簡単ですので、Redisのは、シングルスレッドであるため。クライアントの一般的なRedisのコマンドを受信した後、すぐに実行されますが、クライアントが開始マルチコマンドならば、Redisのはキューにすぐに起こるが、トランザクションコンテキストに現在の接続を聞かせて、コマンドはありません、EXECコマンドを受信し、意志のRedisコマンドは、順次キュー。そして、その結果の実装は、一緒にパッケージクライアントに返され、それがトランザクションコンテキストを終えました。
シンプルなトランザクション制御

 

 
 

 

この例では見ることができます:2つの設定コマンドが発行されますが、キューにすぐに実行されず、Redisのは、execコマンドが実行を開始しました。
2つのスレッドが同時に変数の値を変更した場合、どのようにトランザクションを制御するためにロールバックされますか?どのように楽観的ロック制御で見てみましょうか?
第二に、楽観的ロック制御トランザクション
1.楽観的ロックとは何ですか?
主にデータの記録機構のバージョンをベース。データのバージョンは何ですか?データは、データを読み出す際に、バージョンフィールドを追加するためにデータベース・テーブルのバージョン識別子を追加した後、データベースのバージョンは、データベースの修正バージョンが変更と共に提出+1になるように、一緒に読み取ります。提出されたデータのバージョン番号>はデータベース現在のバージョン番号は、正常に送信された場合。図:

 

 
 


実施例2は、楽観的ロックは
、アカウント情報データベーステーブルは、バージョンフィールドを有していると仮定、現在の値が1である、口座残高が$ 500であります

 
 

 

これは、テーブルに記録された古いデータを変更することにより、オペレータBの可能性を回避します。
3. Redisのは、どのように反映しましたか?
キーは、提出前に変更された場合、提出が失敗し、キーを使用してモニターの腕時計をRedisの。次のとおりです。

 

 
 


当session1还没来得及对age进行修改,session2已经将age的值设为30,session1再执行的时候失败,因为session1对age加了乐观锁的缘故。
watch命令会监视key,当exec时如果监视的key从调用watch后发生过变化,则整个事务会失败。也可以调用watch多次监视多个key。
三、redis事务存在的问题
redis保证事务中的命令连续执行,但是如果其中一条命令执行失败,事务并不回滚。

 
 

 

 

为age +1的命令成功,因为anme是string类型的,所以不能做加操作,命令有一个失败也不会回滚,age的值已经被修改了

おすすめ

転載: www.cnblogs.com/starluke/p/11845207.html