Redis原子計(jì)數(shù)器incr

一崇呵、前言

在一些對(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;
    }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末辜梳,一起剝皮案震驚了整個(gè)濱河市粱甫,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌作瞄,老刑警劉巖茶宵,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異宗挥,居然都是意外死亡乌庶,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門契耿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)瞒大,“玉大人,你說(shuō)我怎么就攤上這事宵喂】飞猓” “怎么了?”我有些...
    開(kāi)封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵锅棕,是天一觀的道長(zhǎng)拙泽。 經(jīng)常有香客問(wèn)我,道長(zhǎng)裸燎,這世上最難降的妖魔是什么顾瞻? 我笑而不...
    開(kāi)封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮德绿,結(jié)果婚禮上荷荤,老公的妹妹穿的比我還像新娘退渗。我一直安慰自己,他們只是感情好蕴纳,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布会油。 她就那樣靜靜地躺著,像睡著了一般古毛。 火紅的嫁衣襯著肌膚如雪翻翩。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天稻薇,我揣著相機(jī)與錄音嫂冻,去河邊找鬼。 笑死塞椎,一個(gè)胖子當(dāng)著我的面吹牛桨仿,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播案狠,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼服傍,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了莺戒?” 一聲冷哼從身側(cè)響起伴嗡,我...
    開(kāi)封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤急波,失蹤者是張志新(化名)和其女友劉穎从铲,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體澄暮,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡名段,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了泣懊。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片伸辟。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖馍刮,靈堂內(nèi)的尸體忽然破棺而出信夫,到底是詐尸還是另有隱情,我是刑警寧澤卡啰,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布静稻,位于F島的核電站,受9級(jí)特大地震影響匈辱,放射性物質(zhì)發(fā)生泄漏振湾。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一亡脸、第九天 我趴在偏房一處隱蔽的房頂上張望押搪。 院中可真熱鬧树酪,春花似錦、人聲如沸大州。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)厦画。三九已至绵载,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間苛白,已是汗流浹背娃豹。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留购裙,地道東北人懂版。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像躏率,于是被迫代替她去往敵國(guó)和親躯畴。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

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