redis lua限流算法实现示例

 更新时间:2022年07月15日 12:01:52   作者:时光沉旧了少年  
这篇文章主要为大家介绍了redis lua限流算法实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

限流算法

常见的限流算法

  • 计数器算法
  • 漏桶算法
  • 令牌桶算法

计数器算法

  顾名思义,计数器算法是指在一定的时间窗口内允许的固定数量的请求.比如,2s内允许10个请求,30s内允许100个请求等等.如果设置的时间粒度越细,那么相对而言限流就会越平滑,控制的粒度就会更细.

场景分析

试想,如果设置的粒度比较粗会出现什么样的问题呢?如下图设置一个 1000/3s 的限流计数统计.

图中的限流策略为3s内允许的最大请求量为1000,那么会出现2个极端:
 

极端情况1:

  • 第1s请流量为10,  
  • 第2s请流量为10,  
  • 第3s请流量突然激增到980.这意味着在这一刻,有大量的请求蜂拥而至,假设服务每秒能处理的

上线为800/1s,但是此刻却有超过这个量级的请求量,那么后果是不堪设想的.

极端情况2:  

  • 第1s请流量突然就达到990,
  • 留给后续第2s,3s的可请求数量就非常少了,可能会出现大量的拒绝请求.

结论:

如果用统计计数算法,尽量保持粒度切割精细.

算法实现

redis的ttl特性完美的满足了这一需求,将时间窗口设置为key的失效时间,然后将key的值每次请求+1即可.伪代码实现思路:

//1.判断是否存在该key
if(EXIT(key)){
  // 1.1自增后判断是否大于最大值,并返回结果
  if(INCR(key) > maxPermit){
     return false;
  }
 return true;
}
//2.不存在key,则设置key初始值为1,失效时间为3秒
SET(KEY,1);
EXPIRE(KEY,3);

漏铜算法

漏桶算法核心概念:

  • 桶的容量是固定的,并且水流以一个固定的速率流出;
  • 流入的水流可以是任意速率;
  • 如果流入的水流超出了桶的容量,则后续流入的水流溢出(请求被丢弃)。
  • 如果桶内没有水,则不需要流出

缺点:

不难想象漏桶算法并不能很好的应对突发的流量限制,在某一个时间段流量激增,则漏桶算法处理就比较无能为力.这个时候就需要用到和他相反设计的令牌桶算法

令牌桶算法:

如上图所示,整个请求流程一目了然.简单概括如下:

1.用户请求资源时首选从桶里获取令牌,如果有令牌则放行,如此同时桶里的令牌数量-1

2.于此同时,以一定的速率往桶里加入令牌,这个速度是可根据实际场景随意设置.

算法实现

var key;
var maxPermit;//桶的容量,即最大请求限制
var expire;//失效时间
var bucketInterval;//每次向桶里添加令牌的时间间隔
var bucketNum;//每次向桶里添加令牌的个数
var lastTimeKey = key +"last";//标记上一次操作时间
//判断是否存在该key
if(EXIT(key)){
  var value = GET(key);
  var diffTime = now() - lastTimeKey;
  // 1.1判断是否超出时间间隔
  if(diffTime  > bucketInterval){
      // 1.2根据时间间隔,计算出应该向桶里添加令牌的个数
      local maxValue = value+math.floor(diff/interval)*step;
      if (maxValue > limit)
         value = limit;
      else
         value = maxValue;
     //设置key的值及操作时间
     SET(key,value);
     SET(lastTimeKey,now());     
  }
  // 2.1在时间间隔内,判断桶里是否有值
  if(value <= 0){
     reurn false;
  }else{
    // 2.2 减1
    DECR(key);
  }
reture true;
}
//2.不存在key,则设置key初始值为maxPermit-1
SET(key,maxPermit-1);
EXPIRE(lastTimeKey,now());

上面实现代码只是伪代码,提供的是一种思路而已. 仔细想来其中某个环节其实并不完美.大家可以参考Guava的ratelimit实现思路,他的限流就是基于令牌桶算法,但是比较遗憾的是在单机下的限流.

思考:  

就是时间间隔如果过长的话,一次性向桶里添加的令牌数量则是桶的最大容量!那么某个时间的瞬间请求过来,服务器的压力是非常大的.

所以此处增加令牌数可以设置的稍微合理些,哪怕间隔时间再长!

以上就是redis lua限流算法实现示例的详细内容,更多关于redis lua限流算法的资料请关注脚本之家其它相关文章!

相关文章

  • 如何操作Redis和zookeeper实现分布式锁

    如何操作Redis和zookeeper实现分布式锁

    这篇文章主要介绍了如何操作Redis和zookeeper实现分布式锁的相关资料,需要的朋友可以参考下
    2017-07-07
  • 多维度深入分析Redis的5种基本数据结构

    多维度深入分析Redis的5种基本数据结构

    此篇文章主要对Redis的5种基本数据类型,即字符串(String)、列表(List)、散列(Hash)、集合(Set)、有序集合(Sorted Set),从使用场景和底层结构出发,进行多维度深入分析。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-11-11
  • Redis简介

    Redis简介

    Redis是一个开源,高级的键值存储和一个适用的解决方案,用于构建高性能,可扩展的Web应用程序。关于redis的相关知识大家可以通过本教程学习
    2017-05-05
  • Redis5之后版本的高可用集群搭建的实现

    Redis5之后版本的高可用集群搭建的实现

    这篇文章主要介绍了Redis5之后版本的高可用集群搭建的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Redis内存空间占用及避免数据丢失的方法

    Redis内存空间占用及避免数据丢失的方法

    在现代的互联网应用中,Redis作为一种高性能的内存数据库,被广泛应用于缓存、会话管理和消息队列等场景,然而,Redis的内存资源是有限的,过多的内存占用可能会导致数据丢失所以本文将给大家介绍一下Redis内存空间占用及避免数据丢失的方法
    2023-08-08
  • Redis哨兵模式的实现

    Redis哨兵模式的实现

    Redis的哨兵模式是一种用于自动监控Redis实例状态并在主服务器出现故障时自动切换到从服务器的机制,本文主要介绍了Redis哨兵模式的实现,感兴趣的可以了解一下
    2024-02-02
  • 浅谈Redis中的缓存更新策略

    浅谈Redis中的缓存更新策略

    这篇文章主要介绍了浅谈Redis中的缓存更新策略,CacheAsidePatter是我们比较常用的缓存更新策略,其由缓存调用者在更新数据库时,在业务逻辑中设置缓存更新,需要的朋友可以参考下
    2023-08-08
  • 缓存替换策略及应用(以Redis、InnoDB为例)

    缓存替换策略及应用(以Redis、InnoDB为例)

    本文以Redis、InnoDB为例给大家讲解缓存替换策略及应用,本文给大家提到五种置换策略,通过实例代码给大家介绍的非常详细,需要的朋友参考下吧
    2021-07-07
  • Redis如何使用HyperLogLog的实现

    Redis如何使用HyperLogLog的实现

    本文主要介绍了Redis如何使用HyperLogLog的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • redis缓存与数据库一致性的问题及解决

    redis缓存与数据库一致性的问题及解决

    这篇文章主要介绍了redis缓存与数据库一致性的问题及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-06-06

最新评论