redis如何實(shí)現(xiàn)限流?3種實(shí)現(xiàn)方式介紹

第一種:基于Redis的setnx的操作

我們在使用Redis的分布式鎖的時(shí)候剔交,大家都知道是依靠了setnx的指令肆饶,在CAS(Compare and swap)的操作的時(shí)候,同時(shí)給指定的key設(shè)置了過期實(shí)踐(expire)岖常,我們在限流的主要目的就是為了在單位時(shí)間內(nèi)驯镊,有且僅有N數(shù)量的請求能夠訪問我的代碼程序。所以依靠setnx可以很輕松的做到這方面的功能腥椒。

比如我們需要在10秒內(nèi)限定20個(gè)請求阿宅,那么我們在setnx的時(shí)候可以設(shè)置過期時(shí)間10,當(dāng)請求的setnx數(shù)量達(dá)到20時(shí)候即達(dá)到了限流效果笼蛛。代碼比較簡單就不做展示了洒放。

當(dāng)然這種做法的弊端是很多的,比如當(dāng)統(tǒng)計(jì)1-10秒的時(shí)候滨砍,無法統(tǒng)計(jì)2-11秒之內(nèi)往湿,如果需要統(tǒng)計(jì)N秒內(nèi)的M個(gè)請求妖异,那么我們的Redis中需要保持N個(gè)key等等問題

第二種:基于Redis的數(shù)據(jù)結(jié)構(gòu)zset

其實(shí)限流涉及的最主要的就是滑動窗口,上面也提到1-10怎么變成2-11领追。其實(shí)也就是起始值和末端值都各+1即可他膳。

而我們?nèi)绻肦edis的list數(shù)據(jù)結(jié)構(gòu)可以輕而易舉的實(shí)現(xiàn)該功能

我們可以將請求打造成一個(gè)zset數(shù)組,當(dāng)每一次請求進(jìn)來的時(shí)候绒窑,value保持唯一棕孙,可以用UUID生成,而score可以用當(dāng)前時(shí)間戳表示些膨,因?yàn)閟core我們可以用來計(jì)算當(dāng)前時(shí)間戳之內(nèi)有多少的請求數(shù)量蟀俊。而zset數(shù)據(jù)結(jié)構(gòu)也提供了range方法讓我們可以很輕易的獲取到2個(gè)時(shí)間戳內(nèi)有多少請求

代碼如下

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是限流的時(shí)間

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秒內(nèi)至多M個(gè)請求订雾,缺點(diǎn)就是zset的數(shù)據(jù)結(jié)構(gòu)會越來越大肢预。實(shí)現(xiàn)方式相對也是比較簡單的。

第三種:基于Redis的令牌桶算法

提到限流就不得不提到令牌桶算法了洼哎。令牌桶算法又稱之為水桶算法烫映,具體可以參照度娘的解釋 令牌桶算法

令牌桶算法提及到輸入速率和輸出速率,當(dāng)輸出速率大于輸入速率噩峦,那么就是超出流量限制了锭沟。

也就是說我們每訪問一次請求的時(shí)候,可以從Redis中獲取一個(gè)令牌壕探,如果拿到令牌了冈钦,那就說明沒超出限制,而如果拿不到李请,則結(jié)果相反瞧筛。

依靠上述的思想,我們可以結(jié)合Redis的List數(shù)據(jù)結(jié)構(gòu)很輕易的做到這樣的代碼

依靠List的leftPop來獲取令牌

//?輸出令牌

public?Response?limitFlow2(Long?id){

Object?result?=?redisTemplate.opsForList().leftPop("limit_list");

if(result?==?null){

return?Response.ok("當(dāng)前令牌桶中無令牌");

}

return?Response.ok(articleDescription2);

}

再依靠Java的定時(shí)任務(wù)导盅,定時(shí)往List中rightPush令牌较幌,當(dāng)然令牌也需要唯一性,所以我這里還是用UUID進(jìn)行了生成

//?10S的速率往令牌桶中添加UUID白翻,只為保證唯一性

@Scheduled(fixedDelay?=?10_000,initialDelay?=?0)

public?void?setIntervalTimeTask(){

redisTemplate.opsForList().rightPush("limit_list",UUID.randomUUID().toString());

}

綜上乍炉,代碼實(shí)現(xiàn)起始都不是很難,針對這些限流方式我們可以在AOP或者filter中加入以上代碼滤馍,用來做到接口的限流岛琼,最終保護(hù)你的網(wǎng)站。

Redis其實(shí)還有很多其他的用處巢株,他的作用不僅僅是緩存槐瑞,分布式鎖的作用。他的數(shù)據(jù)結(jié)構(gòu)也不僅僅是只有String阁苞,Hash困檩,List祠挫,Set,Zset悼沿。有興趣的可以后續(xù)了解下他的GeoHash算法等舔;BitMap,HLL以及布隆過濾器數(shù)據(jù)(Redis4.0之后加入糟趾,可以用Docker直接安裝redislabs/rebloom)結(jié)構(gòu)慌植。

本文來自PHP中文網(wǎng)的redis教程?欄目:https://www.php.cn/redis/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市拉讯,隨后出現(xiàn)的幾起案子涤浇,更是在濱河造成了極大的恐慌,老刑警劉巖魔慷,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異著恩,居然都是意外死亡院尔,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門喉誊,熙熙樓的掌柜王于貴愁眉苦臉地迎上來邀摆,“玉大人,你說我怎么就攤上這事伍茄《绊铮” “怎么了?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵敷矫,是天一觀的道長例获。 經(jīng)常有香客問我,道長曹仗,這世上最難降的妖魔是什么榨汤? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮怎茫,結(jié)果婚禮上收壕,老公的妹妹穿的比我還像新娘。我一直安慰自己轨蛤,他們只是感情好蜜宪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著祥山,像睡著了一般圃验。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上枪蘑,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天损谦,我揣著相機(jī)與錄音岖免,去河邊找鬼。 笑死照捡,一個(gè)胖子當(dāng)著我的面吹牛颅湘,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播栗精,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼闯参,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了悲立?” 一聲冷哼從身側(cè)響起鹿寨,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎薪夕,沒想到半個(gè)月后脚草,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡原献,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年馏慨,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片姑隅。...
    茶點(diǎn)故事閱讀 40,127評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡写隶,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出讲仰,到底是詐尸還是另有隱情慕趴,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布鄙陡,位于F島的核電站冕房,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏柔吼。R本人自食惡果不足惜毒费,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望愈魏。 院中可真熱鬧觅玻,春花似錦、人聲如沸培漏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽牌柄。三九已至畸悬,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間珊佣,已是汗流浹背蹋宦。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工披粟, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人冷冗。 一個(gè)月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓守屉,卻偏偏與公主長得像,于是被迫代替她去往敵國和親蒿辙。 傳聞我的和親對象是個(gè)殘疾皇子拇泛,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評論 2 355