高併發下漏洞桶限流設計方案 - Redis

背景

在咱們作社區的時候,常常會出現發水帖的同窗。對於這種惡意刷帖的,咱們的運營同窗非常頭疼,並且這種還不能在網關進行ip之類的過濾,只能基於單個單個用戶進行處理,咱們常常策略就是:每分鐘發帖次數不能超過2個,超事後就關小黑屋10分鐘。redis

出現場景

  1. 上面講的發帖的防刷機制。
  2. 廣告流量的防刷。
  3. 接口請求失敗進行熔斷機制處理。
  4. ......

解決方案

對於這種「黑惡」請求,咱們必需要作到是關小黑屋,固然有的系統架構比較大的,在網關層面就已經進行關了,咱們這裏是會在業務層來作,由於咱業務不是很大,固然同窗們也能夠把這個移植到網關層,這樣不用穿透到咱們業務側,最少可以減小咱們機房內部網絡流量。bash

流程圖

流程說明

  1. 接口發起請求,服務端獲取這個接口用戶惟一標識(用戶id,電話號碼...).
  2. 判斷該用戶是否被鎖住,若是鎖住就直接返回錯誤碼。
  3. 未鎖住就將該請求標記,亦或者疊加(疊加有坑,往下面看)。
  4. 進行計算當前用戶在必定時間內是否超過咱們設置的閾值。若是未超過直接返回。
  5. 若是超過,那麼就進行鎖定,再返回,下次請求的時候再進行判斷。

具體方案

以咱們場景爲例子,使用Redis來作分佈式鎖和原子計數器網絡

時間內疊加,判斷疊加值是否超過閾值

這個方案,在不少人設計的時候,都會考慮,看起來也沒有太大問題,主要流程是:架構

  1. 假設咱們使用Redis來進行原子計數,每次進來咱們進行incr操做,而且將咱們的key設置爲一個閾值過時時間.
//將咱們用戶請求量疊加1
$request_nums = Redis::incr('user:1:request:nums',1);
//第一次疊加,設置key的過時時間
if ($request_nums == 1){
    Redis::expire('user:1:request:nums',300);
}

if($request_nums > 10){
    //加入小黑屋,下次再進來就要鎖定判斷
}

...

複製代碼
  1. 每次請求會優先進行疊加,而後在這個有效區間內,計算咱們的請求次數,若是請求次數超過閾值,那麼關小黑屋,要是沒有就繼續走下去。

問題:咋一看是沒有問題,每次計算都在個人區間內,可以保證一個區間內的請求量是沒問題的,並且仍是要咱們Redis的原子計數器,可是這裏有一個問題是,一個用戶兩個時間段內都沒有問題,可是跨時間段這個點是沒有考慮的。分佈式

那麼有辦法解決這個時間推移問題形成時間段計算量不精準的問題嗎?lua

答案是確定有,我接下來是使用了Redis的有序集合來作。spa

請求不進行時間段區分,直接寫入有序集合

大體流程:設計

  1. 每次請求就寫入有序集合裏面,集合的sorce值是當前毫秒時間戳(防止秒出現重複),能夠認爲每一次請求就一個時間戳在裏面。
  2. 從集合裏面去掉10分鐘之前全部的集合數據。而後計算出當前的集合裏面數量
  3. 根據這個數量來與咱們閾值作大小判斷,若是超過就鎖住,不然繼續走下去
//將咱們時間戳寫入咱們redis的有序集合裏面
 Redis::zadd('user:1:request:nums',1561456435,'1561456435.122');
//設置key的過時時間爲10分鐘
Redis::expire('user:1:request:nums',300);
//刪除咱們10分鐘之前的數據
Redis::ZREMRANGEBYSCORE('user:1:request:nums',0,1561456135);
//獲取裏面剩下請求個數
$request_nums=(int)Redis::zcard(self::TIMELINE_ELEVEL_KEY);
if($request_nums >= 10){
    //加入小黑屋,下次再進來就要鎖定判斷
}
...

複製代碼

由於咱們不是單純記錄數值,而是會將請求時間記錄下來,那麼隨着時間推移,咱們的請求數統計是不會斷代的。code

總結

  1. 在開始的時候,我一直在想第一個方案的問題所在,後來在討論方案時候,老是發現時間移動,數值應該是會更改,可在第一個方案內,咱們的請求量是不會更改,咱們時間段已經固化成數值了。
  2. 總體的方案設計咱們使用到的Redis的有序集合來作,固然有更好的方案歡迎你們來推薦哈,這個對於redis的讀寫壓力很大的,可是做爲臨時的數據存儲,這個場景仍是比較符合。
  3. 咱們redis的全部操做建議使用原子化來進行,這個可使用官方提供的lua腳原本將多個語句合併成一個語句,而且lua執行速率也是很高。

謝謝你們閱讀!!!cdn

相關文章
相關標籤/搜索