架构师如何讲解Redis限流 您所在的位置:网站首页 限流器怎么用 架构师如何讲解Redis限流

架构师如何讲解Redis限流

2023-12-20 06:56| 来源: 网络整理| 查看: 265

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

本文已参与 「掘力星计划」 ,赢取创作大礼包,挑战创作激励金。

1、需求

限定用户的某个行为在指定时间T内,只允许发生N次。假设T为1秒钟,N为1000次。

2、常见的错误设计

程序员设计了一个在每分钟内只允许访问1000次的限流方案,如下图01:00s-02:00s之间只允许访问1000次,这种设计最大的问题在于,请求可能在01:59s-02:00s之间被请求1000次,02:00s-02:01s之间被请求了1000次,这种情况下01:59s-02:01s间隔0.02s之间被请求2000次,很显然这种设计是错误的。 错误限流.png

3、滑动窗口算法 3.1 解决方案

指定时间T内,只允许发生N次。我们可以将这个指定时间T,看成一个滑动时间窗口(定宽)。我们采用Redis的zset基本数据类型的score来圈出这个滑动时间窗口。在实际操作zset的过程中,我们只需要保留在这个滑动时间窗口以内的数据,其他的数据不处理即可。

每个用户的行为采用一个zset存储,score为毫秒时间戳,value也使用毫秒时间戳(比UUID更加节省内存) 只保留滑动窗口时间内的行为记录,如果zset为空,则移除zset,不再占用内存(节省内存)

zset滑动窗口限流.png

3.2 pipeline代码实现

代码的实现的逻辑是统计滑动窗口内zset中的行为数量,并且与阈值maxCount直接进行比较就可以判断当前行为是否被允许。这里涉及多个redis操作,因此使用pipeline可以大大提升效率

package com.lizba.redis.limit; import redis.clients.jedis.Jedis; import redis.clients.jedis.Pipeline; import redis.clients.jedis.Response; /**  * 

 *     通过zset实现滑动窗口算法限流  * 

 *  * @Author: Liziba  * @Date: 2021/9/6 18:11  */ 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 count = pipe.zcard(key);         // 设置行为的过期时间,如果数据为冷数据,zset将会删除以此节省内存空间         pipe.expire(key, period);         pipe.exec();         pipe.close();         return count.get() 


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有