Redis限流——滑動窗口限流


滑動窗口算法

指定時間T內,只允許發生N次。我們可以將這個指定時間T,看成一個滑動時間窗口(定寬)。
我們 采用Redis的zset基本數據類型的score來圈出這個滑動時間窗口。在實際操作zset的過程中,我們只需要保留在這個滑動時間窗口以內的數據,其他的數據不處理即可。
  • 每個用戶的行為采用一個zset存儲,score為毫秒時間戳,value也使用毫秒時間戳(比UUID更加節省內存)
  • 只保留滑動窗口時間內的行為記錄,如果zset為空,則移除zset,不再占用內存(節省內存)

 

 

pipeline代碼實現

代碼的實現的邏輯是統計滑動窗口內zset中的行為數量,並且與閾值maxCount直接進行比較就可以判斷當前行為是否被允許。這里涉及多個redis操作,因此使用pipeline可以大大提升效率

public class SimpleSlidingWindowByZSet {

    private Jedis jedis;

    public SimpleSlidingWindowByZSet(Jedis jedis) {
        this.jedis = jedis;
    }

    /**
     * 判斷行為是否被允許
     *
     * @param userId        用戶id
     * @param actionKey     行為key
     * @param period        限流周期
     * @param maxCount      最大請求次數(滑動窗口大小)
     * @return
     */
    public boolean isActionAllowed(String userId, String actionKey, int period, int maxCount) {
        String key this.key(userId, actionKey);
        long ts = System.currentTimeMillis();
        Pipeline pipe = jedis.pipelined();
        pipe.multi();
        pipe.zadd(key, ts, String.valueOf(ts));
        // 移除滑動窗口之外的數據
        pipe.zremrangeByScore(key, 0, ts - (period * 1000));
        Response<Long> count = pipe.zcard(key);
        // 設置行為的過期時間,如果數據為冷數據,zset將會刪除以此節省內存空間
        pipe.expire(key, period);
        pipe.exec();
        pipe.close();
        return count.get() <= maxCount;
    }

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM