中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Redis原子計數器incr如何防止并發請求

發布時間:2020-09-30 16:09:39 來源:億速云 閱讀:181 作者:小新 欄目:關系型數據庫

這篇文章將為大家詳細講解有關Redis原子計數器incr如何防止并發請求,小編覺得挺實用的,因此分享給大家做個參考,希望大家閱讀完這篇文章后可以有所收獲。

一、前言

在一些對高并發請求有限制的系統或者功能里,比如說秒殺活動,或者一些網站返回的當前用戶過多,請稍后嘗試。這些都是通過對同一時刻請求數量進行了限制,一般用作對后臺系統的保護,防止系統因為過大的流量沖擊而崩潰。對于系統崩潰帶來的后果,顯然還是拒絕一部分請求更能被維護者所接受。
而在各種限流中,除了系統自身設計的帶鎖機制的計數器外,利用Redis實現顯然是一種既高效安全又便捷方便的方式。

二、incr命令

Redis Incr 命令將 key 中儲存的數字值增一。
如果 key 不存在,那么 key 的值會先被初始化為 0 ,然后再執行 INCR 操作。
如果值包含錯誤的類型,或字符串類型的值不能表示為數字,那么返回一個錯誤。
本操作的值限制在 64 位(bit)有符號數字表示之內。
示例:

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    # 數字值在 Redis 中以字符串的形式保存
"11"

注意: 由于redis并沒有一個明確的類型來表示整型數據,所以這個操作是一個字符串操作。

執行這個操作的時候,key對應存儲的字符串被解析為10進制的64位有符號整型數據。
事實上,Redis 內部采用整數形式(Integer representation)來存儲對應的整數值,所以對該類字符串值實際上是用整數保存,也就不存在存儲整數的字符串表示(String representation)所帶來的額外消耗。

三、使用場景

1.計數器

使用思路是:每次有相關操作的時候,就向Redis服務器發送一個incr命令。
例如這樣一個場景:我們有一個web應用,我們想記錄每個用戶每天訪問這個網站的次數。
web應用只需要通過拼接用戶id和代表當前時間的字符串作為key,每次用戶訪問這個頁面的時候對這個key執行一下incr命令。

這個場景可以有很多種擴展方法:
通過結合使用INCR和EXPIRE命令,可以實現一個只記錄用戶在指定間隔時間內的訪問次數的計數器
客戶端可以通過GETSET命令獲取當前計數器的值并且重置為0
通過類似于DECR或者INCRBY等原子遞增/遞減的命令,可以根據用戶的操作來增加或者減少某些值 比如在線游戲,需要對用戶的游戲分數進行實時控制,分數可能增加也可能減少。

2.限速器

限速器是一種可以限制某些操作執行速率的特殊場景。
傳統的例子就是限制某個公共api的請求數目。
假設我們要解決如下問題:限制某個api每秒每個ip的請求次數不超過10次。
我們可以通過incr命令來實現兩種方法解決這個問題。

四、流量控制之java實現

這里我們將在java中使用redis-incr的特性來構建一個1分鐘內只允許 請求100次的控制代碼,key代表在redis內存放的被控制的鍵值。

public static boolean flowControl(String key){
        //最大允許100
        int max = 100;
        long total = 1L;
        try {
            if (jedisInstance.get(key) == null) {
                //jedisInstance是Jedis連接實例,可以使單鏈接也可以使用鏈接池獲取,實現方式請參考之前的blog內容
                //如果redis目前沒有這個key,創建并賦予0,有效時間為60s
                jedisInstance.setex(key, 60, "0");
            } else {
                //獲取加1后的值
                total = jedisInstance.incr(redisKey).longValue();
                //Redis TTL命令以秒為單位返回key的剩余過期時間。當key不存在時,返回-2。當key存在但沒有設置剩余生存時間時,返回-1。否則,以秒為單位,返回key的剩余生存時間。
                if (jedisInstance.ttl(redisKey).longValue() == -1L)
                {
                    //為給定key設置生存時間,當key過期時(生存時間為0),它會被自動刪除。
                    jedisInstance.expire(redisKey, 60);
                }
            }
        } catch (Exception e) {
            logger.error("流量控制組件:執行計數操作失敗,無法執行計數");
        }
        long keytotaltransations = max;
        //判斷是否已超過最大值,超過則返回false
        if (total > keytotaltransations) {
            return false;
        }
        return true;
    }

關于Redis原子計數器incr如何防止并發請求就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

金沙县| 桃园市| 隆子县| 怀化市| 镇远县| 定陶县| 高平市| 额济纳旗| 丰都县| 霍邱县| 潜山县| 六枝特区| 潞城市| 德钦县| 年辖:市辖区| 华宁县| 京山县| 宁阳县| 宁化县| 酉阳| 喀什市| 道真| 土默特右旗| 恩平市| 佛学| 临武县| 永吉县| 绵竹市| 乡宁县| 崇明县| 芜湖县| 炎陵县| 武冈市| 文昌市| 英超| 漳浦县| 石阡县| 汉阴县| 扎兰屯市| 札达县| 灵武市|