8.【Redis系列】Redis的高級(jí)應(yīng)用-簡(jiǎn)單限流

限流在分布式系統(tǒng)中是一個(gè)經(jīng)常被提到的話題辉词,如果當(dāng)前系統(tǒng)的能力喉脖,不足以承受那么大的訪問量的時(shí)候况鸣,那么我們就要阻止外來請(qǐng)求對(duì)系統(tǒng)繼續(xù)施壓

實(shí)現(xiàn)簡(jiǎn)單限流

首先我們來看一個(gè)常見的簡(jiǎn)單限流策略何乎,系統(tǒng)要限制每個(gè)用戶在一定時(shí)間內(nèi)的某個(gè)行為只能操作N次昔搂,如何是用redis的數(shù)據(jù)結(jié)構(gòu)來實(shí)現(xiàn)這個(gè)限流的功能呢玲销。

解決方案

這個(gè)限流需求中存在一個(gè)滑動(dòng)時(shí)間窗口,想想 zset 數(shù)據(jù)結(jié)構(gòu)的 score 值摘符,是不是可以通過 score 來圈出這個(gè)時(shí)間窗口來贤斜。而且我們只需要保留這個(gè)時(shí)間窗口,窗口之外的數(shù)據(jù)都可以砍掉逛裤。那這個(gè) zset 的 value 填什么比較合適呢瘩绒?它只需要保證唯一性即可,用 uuid 會(huì)比較浪費(fèi)空間带族,那就改用毫秒時(shí)間戳吧锁荔。


image.png

如圖所示,用一個(gè) zset 結(jié)構(gòu)記錄用戶的行為歷史蝙砌,每一個(gè)行為都會(huì)作為 zset 中的一個(gè) key 保存下來阳堕。同一個(gè)用戶同一種行為用一個(gè) zset 記錄。

為節(jié)省內(nèi)存择克,我們只需要保留時(shí)間窗口內(nèi)的行為記錄恬总,同時(shí)如果用戶是冷用戶,滑動(dòng)時(shí)間窗口內(nèi)的行為是空記錄肚邢,那么這個(gè) zset 就可以從內(nèi)存中移除壹堰,不再占用空間。

通過統(tǒng)計(jì)滑動(dòng)窗口內(nèi)的行為數(shù)量與閾值 max_count 進(jìn)行比較就可以得出當(dāng)前的行為是否允許骡湖。用代碼表示如下:

public class SimpleRateLimiter {

  private Jedis jedis;

  public SimpleRateLimiter(Jedis jedis) {
    this.jedis = jedis;
  }

  public boolean isActionAllowed(String userId, String actionKey, int period, int maxCount) {
    String key = String.format("hist:%s:%s", userId, actionKey);
    long nowTs = System.currentTimeMillis();
    Pipeline pipe = jedis.pipelined();
    pipe.multi();
    pipe.zadd(key, nowTs, "" + nowTs);
    pipe.zremrangeByScore(key, 0, nowTs - period * 1000);
    Response<Long> count = pipe.zcard(key);
    pipe.expire(key, period + 1);
    pipe.exec();
    pipe.close();
    return count.get() <= maxCount;
  }

  public static void main(String[] args) {
    Jedis jedis = new Jedis();
    SimpleRateLimiter limiter = new SimpleRateLimiter(jedis);
    for(int i=0;i<20;i++) {
      System.out.println(limiter.isActionAllowed("laoqian", "reply", 60, 5));
    }
  }

}

這段代碼還是略顯復(fù)雜贱纠,需要讀者花一定的時(shí)間好好啃。它的整體思路就是:每一個(gè)行為到來時(shí)响蕴,都維護(hù)一次時(shí)間窗口并巍。將時(shí)間窗口外的記錄全部清理掉,只保留窗口內(nèi)的記錄换途。zset 集合中只有 score 值非常重要懊渡,value 值沒有特別的意義刽射,只需要保證它是唯一的就可以了。

因?yàn)檫@幾個(gè)連續(xù)的 Redis 操作都是針對(duì)同一個(gè) key 的剃执,使用 pipeline 可以顯著提升 Redis 存取效率誓禁。但這種方案也有缺點(diǎn),因?yàn)樗涗洉r(shí)間窗口內(nèi)所有的行為記錄肾档,如果這個(gè)量很大摹恰,比如限定 60s 內(nèi)操作不得超過 100w 次這樣的參數(shù),它是不適合做這樣的限流的怒见,因?yàn)闀?huì)消耗大量的存儲(chǔ)空間俗慈。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市遣耍,隨后出現(xiàn)的幾起案子闺阱,更是在濱河造成了極大的恐慌,老刑警劉巖舵变,帶你破解...
    沈念sama閱讀 212,029評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件酣溃,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡纪隙,警方通過查閱死者的電腦和手機(jī)赊豌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,395評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來绵咱,“玉大人碘饼,你說我怎么就攤上這事”妫” “怎么了艾恼?”我有些...
    開封第一講書人閱讀 157,570評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)拢切。 經(jīng)常有香客問我,道長(zhǎng)秆吵,這世上最難降的妖魔是什么淮椰? 我笑而不...
    開封第一講書人閱讀 56,535評(píng)論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮纳寂,結(jié)果婚禮上主穗,老公的妹妹穿的比我還像新娘。我一直安慰自己毙芜,他們只是感情好忽媒,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,650評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著腋粥,像睡著了一般晦雨。 火紅的嫁衣襯著肌膚如雪架曹。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,850評(píng)論 1 290
  • 那天闹瞧,我揣著相機(jī)與錄音绑雄,去河邊找鬼。 笑死奥邮,一個(gè)胖子當(dāng)著我的面吹牛万牺,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播洽腺,決...
    沈念sama閱讀 39,006評(píng)論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼脚粟,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了蘸朋?” 一聲冷哼從身側(cè)響起核无,我...
    開封第一講書人閱讀 37,747評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎度液,沒想到半個(gè)月后厕宗,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,207評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡堕担,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,536評(píng)論 2 327
  • 正文 我和宋清朗相戀三年已慢,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片霹购。...
    茶點(diǎn)故事閱讀 38,683評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡佑惠,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出齐疙,到底是詐尸還是另有隱情膜楷,我是刑警寧澤,帶...
    沈念sama閱讀 34,342評(píng)論 4 330
  • 正文 年R本政府宣布贞奋,位于F島的核電站赌厅,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏轿塔。R本人自食惡果不足惜特愿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,964評(píng)論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望勾缭。 院中可真熱鬧揍障,春花似錦、人聲如沸俩由。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,772評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽幻梯。三九已至兜畸,卻和暖如春努释,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背膳叨。 一陣腳步聲響...
    開封第一講書人閱讀 32,004評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工洽洁, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人菲嘴。 一個(gè)月前我還...
    沈念sama閱讀 46,401評(píng)論 2 360
  • 正文 我出身青樓饿自,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親龄坪。 傳聞我的和親對(duì)象是個(gè)殘疾皇子昭雌,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,566評(píng)論 2 349

推薦閱讀更多精彩內(nèi)容