小編給大家分享一下redis原子計(jì)數(shù)器incr防止并發(fā)請(qǐng)求指的是什么,希望大家閱讀完這篇文章后大所收獲,下面讓我們一起去探討吧!
成都創(chuàng)新互聯(lián)公司擁有十年成都網(wǎng)站建設(shè)工作經(jīng)驗(yàn),為各大企業(yè)提供網(wǎng)站設(shè)計(jì)、做網(wǎng)站服務(wù),對(duì)于網(wǎng)頁(yè)設(shè)計(jì)、PC網(wǎng)站建設(shè)(電腦版網(wǎng)站建設(shè))、app軟件開(kāi)發(fā)、wap網(wǎng)站建設(shè)(手機(jī)版網(wǎng)站建設(shè))、程序開(kāi)發(fā)、網(wǎng)站優(yōu)化(SEO優(yōu)化)、微網(wǎng)站、域名與空間等,憑借多年來(lái)在互聯(lián)網(wǎng)的打拼,我們?cè)诨ヂ?lián)網(wǎng)網(wǎng)站建設(shè)行業(yè)積累了很多網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、網(wǎng)絡(luò)營(yíng)銷經(jīng)驗(yàn),集策劃、開(kāi)發(fā)、設(shè)計(jì)、營(yíng)銷、管理等網(wǎng)站化運(yùn)作于一體,具備承接各種規(guī)模類型的網(wǎng)站建設(shè)項(xiàng)目的能力。
一、前言
在一些對(duì)高并發(fā)請(qǐng)求有限制的系統(tǒng)或者功能里,比如說(shuō)秒殺活動(dòng),或者一些網(wǎng)站返回的當(dāng)前用戶過(guò)多,請(qǐng)稍后嘗試。這些都是通過(guò)對(duì)同一時(shí)刻請(qǐng)求數(shù)量進(jìn)行了限制,一般用作對(duì)后臺(tái)系統(tǒng)的保護(hù),防止系統(tǒng)因?yàn)檫^(guò)大的流量沖擊而崩潰。對(duì)于系統(tǒng)崩潰帶來(lái)的后果,顯然還是拒絕一部分請(qǐng)求更能被維護(hù)者所接受。
而在各種限流中,除了系統(tǒng)自身設(shè)計(jì)的帶鎖機(jī)制的計(jì)數(shù)器外,利用Redis實(shí)現(xiàn)顯然是一種既高效安全又便捷方便的方式。
二、incr命令
Redis Incr 命令將 key 中儲(chǔ)存的數(shù)字值增一。
如果 key 不存在,那么 key 的值會(huì)先被初始化為 0 ,然后再執(zhí)行 INCR 操作。
如果值包含錯(cuò)誤的類型,或字符串類型的值不能表示為數(shù)字,那么返回一個(gè)錯(cuò)誤。
本操作的值限制在 64 位(bit)有符號(hào)數(shù)字表示之內(nèi)。
示例:
127.0.0.1:6379> set num 10 OK 127.0.0.1:6379> incr num (integer) 11 127.0.0.1:6379> get num # 數(shù)字值在 Redis 中以字符串的形式保存 "11"
注意: 由于redis并沒(méi)有一個(gè)明確的類型來(lái)表示整型數(shù)據(jù),所以這個(gè)操作是一個(gè)字符串操作。
執(zhí)行這個(gè)操作的時(shí)候,key對(duì)應(yīng)存儲(chǔ)的字符串被解析為10進(jìn)制的64位有符號(hào)整型數(shù)據(jù)。
事實(shí)上,Redis 內(nèi)部采用整數(shù)形式(Integer representation)來(lái)存儲(chǔ)對(duì)應(yīng)的整數(shù)值,所以對(duì)該類字符串值實(shí)際上是用整數(shù)保存,也就不存在存儲(chǔ)整數(shù)的字符串表示(String representation)所帶來(lái)的額外消耗。
三、使用場(chǎng)景
1.計(jì)數(shù)器
使用思路是:每次有相關(guān)操作的時(shí)候,就向Redis服務(wù)器發(fā)送一個(gè)incr命令。
例如這樣一個(gè)場(chǎng)景:我們有一個(gè)web應(yīng)用,我們想記錄每個(gè)用戶每天訪問(wèn)這個(gè)網(wǎng)站的次數(shù)。
web應(yīng)用只需要通過(guò)拼接用戶id和代表當(dāng)前時(shí)間的字符串作為key,每次用戶訪問(wèn)這個(gè)頁(yè)面的時(shí)候?qū)@個(gè)key執(zhí)行一下incr命令。
這個(gè)場(chǎng)景可以有很多種擴(kuò)展方法:
通過(guò)結(jié)合使用INCR和EXPIRE命令,可以實(shí)現(xiàn)一個(gè)只記錄用戶在指定間隔時(shí)間內(nèi)的訪問(wèn)次數(shù)的計(jì)數(shù)器
客戶端可以通過(guò)GETSET命令獲取當(dāng)前計(jì)數(shù)器的值并且重置為0
通過(guò)類似于DECR或者INCRBY等原子遞增/遞減的命令,可以根據(jù)用戶的操作來(lái)增加或者減少某些值 比如在線游戲,需要對(duì)用戶的游戲分?jǐn)?shù)進(jìn)行實(shí)時(shí)控制,分?jǐn)?shù)可能增加也可能減少。
2.限速器
限速器是一種可以限制某些操作執(zhí)行速率的特殊場(chǎng)景。
傳統(tǒng)的例子就是限制某個(gè)公共api的請(qǐng)求數(shù)目。
假設(shè)我們要解決如下問(wèn)題:限制某個(gè)api每秒每個(gè)ip的請(qǐng)求次數(shù)不超過(guò)10次。
我們可以通過(guò)incr命令來(lái)實(shí)現(xiàn)兩種方法解決這個(gè)問(wèn)題。
四、流量控制之java實(shí)現(xiàn)
這里我們將在java中使用redis-incr的特性來(lái)構(gòu)建一個(gè)1分鐘內(nèi)只允許 請(qǐng)求100次的控制代碼,key代表在redis內(nèi)存放的被控制的鍵值。
public static boolean flowControl(String key){ //最大允許100 int max = 100; long total = 1L; try { if (jedisInstance.get(key) == null) { //jedisInstance是Jedis連接實(shí)例,可以使單鏈接也可以使用鏈接池獲取,實(shí)現(xiàn)方式請(qǐng)參考之前的blog內(nèi)容 //如果redis目前沒(méi)有這個(gè)key,創(chuàng)建并賦予0,有效時(shí)間為60s jedisInstance.setex(key, 60, "0"); } else { //獲取加1后的值 total = jedisInstance.incr(redisKey).longValue(); //Redis TTL命令以秒為單位返回key的剩余過(guò)期時(shí)間。當(dāng)key不存在時(shí),返回-2。當(dāng)key存在但沒(méi)有設(shè)置剩余生存時(shí)間時(shí),返回-1。否則,以秒為單位,返回key的剩余生存時(shí)間。 if (jedisInstance.ttl(redisKey).longValue() == -1L) { //為給定key設(shè)置生存時(shí)間,當(dāng)key過(guò)期時(shí)(生存時(shí)間為0),它會(huì)被自動(dòng)刪除。 jedisInstance.expire(redisKey, 60); } } } catch (Exception e) { logger.error("流量控制組件:執(zhí)行計(jì)數(shù)操作失敗,無(wú)法執(zhí)行計(jì)數(shù)"); } long keytotaltransations = max; //判斷是否已超過(guò)最大值,超過(guò)則返回false if (total > keytotaltransations) { return false; } return true; }
看完了這篇文章,相信你對(duì)Redis原子計(jì)數(shù)器incr防止并發(fā)請(qǐng)求指的是什么有了一定的了解,想了解更多相關(guān)知識(shí),歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!