REDIS - string類型

來源:互聯網
上載者:User
incr 用法

incr key,可以將key值原子自增1,並返回遞增操作後key對應的新值。如果指定的key不存在,那麼在執行incr操作之前,會先將它的值設定為0。

/*測試前,清除當前資料庫所有key*/127.0.0.1:6379> flushDBOK/*沒有key*/127.0.0.1:6379> keys *(empty list or set) /*使用incr 一個不存在的key,有返回為1(如果指定的key不存在,那麼在執行incr操作之前,會先將它的值設定為0,並返回自增後的值1)*/127.0.0.1:6379> incr incrKey(integer) 1127.0.0.1:6379> get incrKey"1"/*自增1,返回增加後的值2*/127.0.0.1:6379> incr incrKey(integer) 2127.0.0.1:6379> get incrKey"2"              1        2        3        4        5        6        7        8        9        10        11        12        13        14        15        16      
使用情境1 - 計數器

例如:一個web應用,我們想記錄每個使用者每天訪問這個網站的次數。就可以使用這個使用者的id和當天日期拼接一個key,每訪問一次只用incr對該key操作,從而獲得該使用者當天的訪問網站次數。比如使用者id為9eda3e419e6eadb99293f5c9105816c93a0ca760,今日是20161015,則可以使用incr 9eda3e419e6eadb99293f5c9105816c93a0ca760:20161015作為統計該使用者在2016-10-15當天的訪問次數。
該情境的擴充:統計該使用者在某個時間範圍之內的訪問次數,可以結合incr、expire來達到目標。 使用情境2 - 限制訪問次數(一)

假設我們有這樣的需求:每個api介面,每秒每個ip的訪問次數不能超過10次。
我們可以為ip:時間戳記(到秒)設定key,以下使用偽碼展示:

FUNCTION LIMIT_ACCESS_COUNT(ip)currSecond = CURRENT_UNIX_TIME()keyName = ip+":"+currSecondcurrentCnt = GET(keyName)IF currentCnt != NULL AND currentCnt > 10 THEN    ERROR "一秒內訪問次數過多"ELSE    MULTI        /*比如10.192.168.27在2016-10-15 15:20:19時訪問次數不到10,一直自增*/        INCR(keyName,1)          /*計數器每次遞增的時候都設定了10秒的到期時間,這樣在進入下一秒時,redis會自動刪除前一秒的計數器。         *  鍵 10.192.168.27:2016-10-15 15:20:19將會在2016-10-15 15:20:29之後刪除               */        EXPIRE(keyName,10)      EXEC    DO_JOB()END              1        2        3        4        5        6        7        8        9        10        11        12        13        14        15        16        17      
使用情境2 - 限制訪問次數(二)

前面例子是每個ip每一秒都產生一個key。在此例中,我們一個ip只會產生一個key,但是實際使用中需要注意競態條件的出現。
具體思路是:從第一個請求開始設定到期時間為1秒。如果1秒內請求數超過了10個,那麼會提示錯誤資訊。到了下一秒,計數器會清零後重新開始計數。

FUNCTION LIMIT_ACCESS_COUNT(ip)keyName = ipcurrentCnt = GET(keyName)IF currentCnt != NULL AND currentCnt > 10 THEN    ERROR "一秒內訪問次數過多"ELSE    MULTI        /*比如10.192.168.27在2016-10-15 15:20:19時訪問次數不到10,一直自增*/        currentCnt = INCR(ip)        IF currentCnt == 1 THEN        /*計數器每次遞增的時候都設定了1秒的到期時間,只有在第一次訪問時才設定逾時時間為1秒         * 鍵 10.192.168.27:2016-10-15 15:20:19將會在2016-10-15 15:20:20之後刪除               */        EXPIRE(keyName,1)          END    EXEC    DO_JOB()END              1        2        3        4        5        6        7        8        9        10        11        12        13        14        15        16        17        18      

處理競態條件 : 使用LUA指令碼。
在前面的例子中,如果使用incr後,沒有成功執行expire,會導致這個ip的key引起記憶體流失,知道下次有同一個ip發送相同請求過來。可以將可能發生競態條件的邏輯放在LUA指令碼中,再使用eval解決(要求REDIS2.6版本以上)

/*LUA指令碼*/local currentCntcurrentCnt = redis.call("incr",KEYS[1])if tonumber(currentCnt) == 1 then    redis.call("expire",KEYS[1],1)end              1        2        3        4        5        6      
getset

getset key value 會將value設定為key的值,但是返回的是key原來的值。如果key存在但是對應的value不是字串,就返回錯誤。如果之前Key不存在將返回nil。

127.0.0.1:6379> flushDB OK 127.0.0.1:6379> keys * (empty list or set) /使用incr實現計數器自增,使用getset可以重設為0/ 127.0.0.1:6379> incr testKey (integer) 1 127.0.0.1:6379> incr testKey (integer) 2 127.0.0.1:6379> getset testKey 0 “2” 127.0.0.1:6379> get testKey “0”

/key不存在返回nil/
127.0.0.1:6379> getset testKey2 0
(nil) 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.