国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Redis 實(shí)現(xiàn)限流的三種方式

這篇具有很好參考價(jià)值的文章主要介紹了Redis 實(shí)現(xiàn)限流的三種方式。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

面對(duì)越來越多的高并發(fā)場(chǎng)景,限流顯示的尤為重要。

當(dāng)然,限流有許多種實(shí)現(xiàn)的方式,Redis具有很強(qiáng)大的功能,我用Redis實(shí)踐了三種的實(shí)現(xiàn)方式,可以較為簡(jiǎn)單的實(shí)現(xiàn)其方式。Redis不僅僅是可以做限流,還可以做數(shù)據(jù)統(tǒng)計(jì),附近的人等功能,這些可能會(huì)后續(xù)寫到。

一、基于Redis的setnx的操作

我們?cè)谑褂肦edis的分布式鎖的時(shí)候,大家都知道是依靠了setnx的指令,在CAS(Compare and swap)的操作的時(shí)候,同時(shí)給指定的key設(shè)置了過期實(shí)踐(expire),我們?cè)谙蘖鞯闹饕康木褪菫榱嗽趩挝粫r(shí)間內(nèi),有且僅有N數(shù)量的請(qǐng)求能夠訪問我的代碼程序。所以依靠setnx可以很輕松的做到這方面的功能。

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

當(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è)請(qǐng)求,那么我們的Redis中需要保持N個(gè)key等等問題

推薦下自己做的 Spring Boot 的實(shí)戰(zhàn)項(xiàng)目:

https://github.com/YunaiV/ruoyi-vue-pro

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

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

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

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

代碼如下

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("訪問成功");
}

通過上述代碼可以做到滑動(dòng)窗口的效果,并且能保證每N秒內(nèi)至多M個(gè)請(qǐng)求,缺點(diǎn)就是zset的數(shù)據(jù)結(jié)構(gòu)會(huì)越來越大。實(shí)現(xiàn)方式相對(duì)也是比較簡(jiǎn)單的。

推薦下自己做的 Spring Cloud 的實(shí)戰(zhàn)項(xiàng)目:

https://github.com/YunaiV/onemall

三、基于Redis的令牌桶算法

提到限流就不得不提到令牌桶算法了。

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

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

依靠上述的思想,我們可以結(jié)合Redis的List數(shù)據(jù)結(jié)構(gòu)很輕易的做到這樣的代碼,只是簡(jiǎn)單實(shí)現(xiàn)

依靠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)起始都不是很難,針對(duì)這些限流方式我們可以在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)。文章來源地址http://www.zghlxwxcb.cn/news/detail-515559.html

到了這里,關(guān)于Redis 實(shí)現(xiàn)限流的三種方式的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 服務(wù)限流的六種方式

    服務(wù)限流,是指通過控制請(qǐng)求的速率或次數(shù)來達(dá)到保護(hù)服務(wù)的目的,在微服務(wù)中,我們通常會(huì)將它和熔斷、降級(jí)搭配在一起使用,來避免瞬時(shí)的大量請(qǐng)求對(duì)系統(tǒng)造成負(fù)荷,來達(dá)到保護(hù)服務(wù)平穩(wěn)運(yùn)行的目的。下面就來看一看常見的6種限流方式,以及它們的實(shí)現(xiàn)與使用。 固定窗

    2024年02月10日
    瀏覽(21)
  • 前端單點(diǎn)登錄實(shí)現(xiàn)的三種方式

    1.同源不跨域 使用document.cookie或者localStorage可以直接存取 2.跨域主域名相同 可以使用cookie-js插件存儲(chǔ)cookie,在設(shè)置cookie是添加domain參數(shù),例如 Cookies.set(\\\'token\\\', 值, { expires: 60, path: \\\'\\\', domain: \\\'taobao.com\\\' }) 只有主域名相同,瀏覽器在訪問時(shí)才會(huì)攜帶對(duì)應(yīng)的 cookie 3.跨域 使用iframe內(nèi)嵌

    2024年04月27日
    瀏覽(19)
  • Docker 實(shí)現(xiàn)掛載的三種方式

    Docker 實(shí)現(xiàn)掛載的三種方式

    容器中運(yùn)行的應(yīng)用,有可能會(huì)產(chǎn)生數(shù)據(jù),如果將數(shù)據(jù)直接存儲(chǔ)到容器中,如果刪除容器時(shí),容器中的數(shù)據(jù)會(huì)一起被刪除,例如: 如果運(yùn)行的是數(shù)據(jù)庫容器,數(shù)據(jù)庫容器直接保存的數(shù)據(jù)文件,刪除容器時(shí),容易導(dǎo)致數(shù)據(jù)丟失 為了防止數(shù)據(jù)丟失,可以把數(shù)據(jù)保存到宿主機(jī)上,這樣有便于容器之間

    2024年01月23日
    瀏覽(27)
  • SpringBoot實(shí)現(xiàn)分頁的三種方式

    一 自己封裝Page對(duì)象實(shí)現(xiàn) 博客鏈接 二 使用sql實(shí)現(xiàn)分頁 2.1 場(chǎng)景分析 前段傳遞給給后臺(tái)什么參數(shù)? 當(dāng)前頁碼 currentPage 每頁顯示條數(shù) pageSize 后臺(tái)給前端返回什么數(shù)據(jù)? 當(dāng)前頁數(shù)據(jù) List 總記錄數(shù) totalCount 2.2 前段代碼 2.3 后端代碼 PageBean mapper service impl controller 三 使用PageHelper插件

    2024年02月10日
    瀏覽(28)
  • Java 實(shí)現(xiàn)多線程的三種方式

    1、三種方法的介紹和比較 1、1三種方式得介紹 1、繼承Thread類 2、實(shí)現(xiàn)Runnable接口 3、實(shí)現(xiàn)Callable接口 1、2三種方法的介紹和比較 1、2、1、實(shí)現(xiàn)Runnable接口相比繼承Thread類有如下優(yōu)勢(shì) 1、增強(qiáng)程序的健壯性,將業(yè)務(wù)邏輯與線程調(diào)度分離 2、線程池只能放入實(shí)現(xiàn)Runable或Callable類線程

    2024年02月02日
    瀏覽(22)
  • Java 多線程實(shí)現(xiàn)的三種方式

    Java 多線程實(shí)現(xiàn)方式主要有三種:繼承 Thread 類、實(shí)現(xiàn) Runnable 接口、使用 ExecutorService、Callable、Future 實(shí)現(xiàn)有返回結(jié)果的多線程。其中前兩種方式線程執(zhí)行完后都沒有返回值,只有最后一種是帶返回值的。 1、繼承 Thread 類實(shí)現(xiàn)多線程 繼承 Thread 類的方法盡管被我列為一種多線程

    2023年04月27日
    瀏覽(23)
  • vue深拷貝的三種實(shí)現(xiàn)方式

    vue深拷貝的三種實(shí)現(xiàn)方式:1、通過遞歸方式實(shí)現(xiàn)深拷貝;2、JSON.parse(JSON.stringify(obj));3、jQuery的extend方法實(shí)現(xiàn)深拷貝。 深拷貝: 拷貝的是對(duì)象或者數(shù)組內(nèi)部數(shù)據(jù)的實(shí)體,重新開辟了內(nèi)存空間存儲(chǔ)數(shù)據(jù); 淺拷貝: 拷貝的是引用類型的指針,副本和原數(shù)組或?qū)ο笾赶蛲粋€(gè)內(nèi)

    2024年01月25日
    瀏覽(17)
  • 【CSS】文字描邊的三種實(shí)現(xiàn)方式

    【CSS】文字描邊的三種實(shí)現(xiàn)方式

    text-shadow –webkit-text-stroke svg MDN text-shadow 代碼 用 text-shadow 實(shí)現(xiàn)八個(gè)方向的文字陰影。 優(yōu)缺點(diǎn) 優(yōu)點(diǎn) 兼容性好 缺點(diǎn) 文字邊緣會(huì)有鋸齒。 如上圖,當(dāng)文字很大時(shí),尤其明顯。因?yàn)槲覀冎辉O(shè)置了8個(gè)方向的陰影,這些方向交界處容易出問題。 文字必須設(shè)置顏色 如果我們把文字設(shè)

    2024年02月02日
    瀏覽(95)
  • Spark SQL join的三種實(shí)現(xiàn)方式

    join是SQL中的常用操作,良好的表結(jié)構(gòu)能夠?qū)?shù)據(jù)分散到不同的表中,使其符合某種規(guī)范(mysql三大范式),可以最大程度的減少數(shù)據(jù)冗余,更新容錯(cuò)等,而建立表和表之間關(guān)系的最佳方式就是join操作。 對(duì)于Spark來說有3種Join的實(shí)現(xiàn),每種Join對(duì)應(yīng)的不同的應(yīng)用場(chǎng)景(SparkSQL自動(dòng)決策

    2024年02月11日
    瀏覽(29)
  • RabbitMQ 簡(jiǎn)單實(shí)現(xiàn)創(chuàng)建隊(duì)列的三種方式

    //1. 手動(dòng)創(chuàng)建,需在RabbitMQ中手動(dòng)創(chuàng)建myQueue1 隊(duì)列,否則報(bào)錯(cuò) @RabbitListener(queues = “myQueue1”) public void process1(String message){ log.info(“MqReceiver1: {}”, message); } //2. 自動(dòng)創(chuàng)建隊(duì)列 @RabbitListener(queuesToDeclare = @Queue(“myQueue2”)) public void process2(String message){ log.info(“MqReceiver2: {}”, messa

    2024年02月15日
    瀏覽(20)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包