首页 > 数据库 >redis限流和滑动窗口限流

redis限流和滑动窗口限流

时间:2022-10-31 15:57:39浏览次数:73  
标签:LimitQueue redis value 限流 key lock 滑动 queueName

 

一、redis set nx实现限流

 

比如我们需要在10秒内限定20个请求,那么我们在setnx的时候可以设置过期时间为当前时间戳+10s,使用set nx 设置20个互不相同的key,当请求的setnx数量达到20时候即达到了限流效果。

 

当然这种做法的弊端是很多的,比如当统计1-10秒的时候,无法统计2-11秒之内,如果需要统计N秒内的M个请求,那么我们的Redis中需要保持N个key等等问题

 

SETNX 是SET if Not eXists的简写,日常指令是SETNX key value,如果 key 不存在则set成功返回 1,如果这个key已经存在了返回0

底层实现包含三个步骤,用lua脚本保证原子性
1、get:获取这个key
2、比较:比较这个key对应的value是否和自己有关联
3、del:删除这个key

SET lock_key lock_value NX PX 30000
1.lock_key:即锁名称,这个名称应是公开的,在分布式环境中,对于某一确定的公共资源,所有争用方(客户端)都应该知道对应锁的名字。对于 Redis 而言,lock_name 就是 key-value 中的 key,具有唯一性。
2. lock_value:是由客户端生成的一个随机字符串,它要保证在足够长的一段时间内在所有客户端的所有获取锁的请求中都是唯一的,用于唯一标识锁的持有者。
3. NX 表示只有当 lock_key(key) 不存在的时候才能 SET 成功,从而保证只有一个客户端能获得锁,而其它客户端在锁被释放之前都无法获得锁。
4. PX 30000 表示这个锁节点有一个 30 秒的自动过期时间(目的是为了防止持有锁的客户端故障后,无法主动释放锁而导致死锁,因此要求锁的持有者必须在过期时间之内执行完相关操作并释放锁)

 

 

二、redis zset 实现延时队列限流

我们可以将请求打造成一个zset数组,当每一次请求进来的时候,value保持唯一,可以用UUID生成,而score可以用当前时间戳表示,因为score我们可以用来计算当前时间戳之内有多少的请求数量。而zset数据结构也提供了range方法让我们可以很轻易的获取到2个时间戳内有多少请求

 

三、滑动窗口实现限流

 

其本质思想是转换概念,将原本问题的确定时间大小,进行次数限制。转换成确定次数大小,进行时间限制。

https://www.cnblogs.com/taoshihan/p/14132949.html

复制代码
package utils

import "time"

var LimitQueue map[string][]int64
var ok bool

//单机时间滑动窗口限流法
func LimitFreqSingle(queueName string, count uint, timeWindow int64) bool {
    currTime := time.Now().Unix()
    if LimitQueue == nil {
        LimitQueue = make(map[string][]int64)
    }
    if _, ok = LimitQueue[queueName]; !ok {
        LimitQueue[queueName] = make([]int64, 0)
    }
    //队列未满
    if uint(len(LimitQueue[queueName])) < count {
        LimitQueue[queueName] = append(LimitQueue[queueName], currTime)
        return true
    }
    //队列满了,取出最早访问的时间
    earlyTime := LimitQueue[queueName][0]
    //说明最早期的时间还在时间窗口内,还没过期,所以不允许通过
    if currTime-earlyTime <= timeWindow {
        return false
    } else {
        //说明最早期的访问应该过期了,去掉最早期的
        LimitQueue[queueName] = LimitQueue[queueName][1:]
        LimitQueue[queueName] = append(LimitQueue[queueName], currTime)
    }
    return true
}
复制代码

标签:LimitQueue,redis,value,限流,key,lock,滑动,queueName
From: https://www.cnblogs.com/matengfei123/p/16844592.html

相关文章

  • Redis系列8:Bitmap实现亿万级数据计算
    Redis系列1:深刻理解高性能Redis的本质Redis系列2:数据持久化提高可用性Redis系列3:高可用之主从架构Redis系列4:高可用之Sentinel(哨兵模式)Redis系列5:深入分析Cluster集......
  • 3主3从redis集群扩缩容配置案例
    1、环境准备#关闭防火墙systemctlstopfirewalld#查看防火墙状态systemctlstatusfirewalld#拉取redis:6.0.8镜像dockerpullredis:6.0.8  2、新建6个doc......
  • Redis学习十一:Redis持久化
    文章目录​​一、RDB(RedisDataBase)​​​​1.1触发机制​​​​1.2如果恢复rdb文件!​​​​1.3优缺点​​​​二、AOF(AppendOnlyFile)​​​​2.1是什么​​​​2.2appen......
  • Redis学习四:测试性能
    文章目录​​一、使用自带测试工具redis-benchmark​​​​二、测试:100个并发连接100000请求​​一、使用自带测试工具redis-benchmarkredis-benchmark是一个压力测试工具......
  • 通过抓包研究redis连接问题记录
    一、研究问题1:redis配置文件设置了选项timeout后,是否会导致大量close_wait状态连接注:redis配置文件timeout选项说明如下#Closetheconnectionafteraclientisidle......
  • Redis和数据库双写情况下,客户端展示信息未及时生效
    问题现象:后端更新完数据库记录版本号后,前端展示的记录版本号仍然为老的版本号问题分析:客户端展示的版本号是从缓存中获取的,在更新后端数据库记录的时候,采用双写的方式,但......
  • Redis学习笔记
    Redisshodan:"product:Redis"shodan:product:"Rediskey-valuestore"fofa:protocol="redis"Redis基础Redis相关文章细数redis的几种getshell方法......
  • SpringBoot集成Redisson报错RedissonReactiveRedisConnection.close()
    SpringBoot集成redisson-spring-boot-starter报错:点击查看代码2022-10-3109:30:10.255WARN92312---[isson-netty-2-4]io.netty.util.concurrent.DefaultPromise......
  • 浅谈Redis与分布式锁
    后续进行补充,先放个链接在这,哈哈 https://zhuanlan.zhihu.com/p/378797329#:~:text=%E6%83%B3%E8%A6%81%E5%AE%9E%E7%8E%B0%E5%88%86%E5%B8%83%E5%BC%8F%E9%94%81%EF%BC......
  • js滑动验证
    <!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metahttp-equiv="X-UA-Compatible"content="IE=edge"><metaname="viewport"content......