redis 基于 漏斗算法 实现对 api 的限流
漏斗算法
漏桶算法的原理:
漏桶有一定的容量,给漏桶注水,当单位时间内注入水量大于流出水量,漏桶内积累的水就会越来越多,直到溢出。
就好比大批量请求访问nginx相当于注水,nginx根据配置按照固定速率处理请求当做排水。
漏桶容量就好比配置给nginx的队列长度。当漏桶发生溢出,则禁止请求进入,直接返回错误
php实现一个简单的漏斗算法
/**
* [leaky php实现漏桶算法]
* @param [type] $contain [int 桶的总容量]
* @param [type] $addNum [int 每次注入桶中的水量]
* @param [type] $leakRate [int 桶中漏水的速率,秒为单位。例如2/s,3/s]
* @param integer &$water [int 当前水量]
* @param integer &$preTime [int 时间戳,记录的上次漏水时间]
* @return [type] [bool,返回可否继续注入true/false]
*/
function leaky($contain,$addNum,$leakRate,&$water=0,&$preTime=0)
{
//参数赋值
//首次进入默认当前水量为0
$water = empty($water) ? 0 : $water;
//首次进入默认上次漏水时间为当前时间
$preTime = empty($water) ? time() : $preTime;
$curTime = time();
//上次结束到本次开始,流出去的水
$leakWater = ($curTime-$preTime)*$leakRate;
//上次结束时候的水量减去流出去的水,也就是本次初始水量
$water = $water-$leakWater;
//水量不可能为负,漏出大于进入则水量为0
$water = ( $water>=0 ) ? $water : 0 ;
//更新本次漏完水的时间
$preTime = $curTime;
//水小于总容量则可注入,否则不可注入
if( ($water+$addNum) <= $contain ){
$water += $addNum;
return true;
}else{
return false;
}
}
/**
* 测试
* @var integer
*/
for($i=0;$i<500;$i++){
$res = leaky(50,1,5,$water,$timeStamp);
var_dump($res);
usleep(50000);
}
redis 的漏斗算法实现
public function SpeedCounter() {
$redis = new \Redis();
$redis->connect('127.0.0.1', 6379);
// 最大请求数量
$maxCount = 100;
//每分钟内,一个用户只能访问10次
$interval =60;
//请求总数量
$zcount = $redis->incr('zcont');
//判断是否超过最大值
if ($zcount<=$maxCount) {
//业务处理
$user = [
11,21,31,41,51,61
];
foreach ($user as $val) {
$key = $val;
$check = $redis->exists($key);
if ($check) {
$sum = $redis->incr($key);
if ($sum<=5) {
//业务处理
echo "每个用户在规定的时间内只能访问5次 $sum";
} else {
echo "你已经购买过 $sum";
}
} else {
//print_r($redis->get($key)) ;
///请购买
echo "请购买";
$sum = $redis->incr($key);
$redis->Expire($key,$interval);
}
}
} else {
//超过请求数量
$redis->Expire('zcont',$interval);
echo '超出请求'.$zcount;
}
漏桶算法
漏桶的大小是固定的,处理速度也是固定的,但是请求的速率的不固定的。在突发的情况下,会丢弃很多请求。
/**
* **漏桶的大小是固定的,处理速度也是固定的,但是请求的速率的不固定的。在突发的情况下,会丢弃很多请求。**
*/
function LeackBucket() {
$redis = new \Redis();
$redis->connect('127.0.0.1', 6379);
//桶的容量
$maxCount = 1000;
//时间
$interval = 10;
//每分钟流出的数量
$speed = 20;
//用户
$time = $redis->time();
$key = $time[0].$time[1];
//时间判断
//$redis->del('outCount');
$check = $redis->exists('outCount');
// echo $check;
if ($check) {
//出桶的速率的请求数量
$outCount = $redis->incr('outCount');
if ($outCount<=$speed) {
//业务处理
echo "规定的时间内只能访问20次 $outCount";
} else {
echo "你已经超过每分钟的访问 $outCount";
}
} else {
$outCount = $redis->incr('outCount');
// echo $outCount;
$redis->Expire('outCount',$interval);
echo "时间过了";
exit;
}
}
令牌桶
令牌桶算法(Token Bucket)和 Leaky Bucket 效果一样但方向相反的算法,更加容易理解.随着时间流逝,系统会按恒定1/QPS时间间隔(如果QPS=100,则间隔是10ms)往桶里加入Token(想象和漏洞漏水相反,有个水龙头在不断的加水),如果桶已经满了就不再加了.新请求来临时,会各自拿走一个Token,如果没有Token可拿了就阻塞或者拒绝服务.
令牌桶的另外一个好处是可以方便的改变速度. 一旦需要提高速率,则按需提高放入桶中的令牌的速率. 一般会定时(比如100毫秒)往桶中增加一定数量的令牌, 有些变种算法则实时的计算应该增加的令牌的数量.
/**
* 令牌
*/
function TrafficShaper() {
$redis = new \Redis();
$redis->pconnect('127.0.0.1', 6379);
//桶的容量
$maxCount = 10;
//当前容量
$curnum = $maxCount-$redis->get('token')-1;
echo $curnum;
if ($curnum>0) {
//业务逻辑
//成功后
$token = $redis->incr('token');
echo "===$token";
} else {
echo "没有令牌了";
$redis->set('token',0);
}
}
redis基于lua+漏斗算法实现对api的限流
https://mp.weixin.qq.com/s/r3Tpq6EIXZt_djbSEiH8Ew
redis 基于 漏斗算法 实现对 api 的限流的更多相关文章
- 使用JWT来实现对API的授权访问
目录 什么是JWT JWT的结构 Header Payload Signature 解码后的JWT JWT是怎样工作的 在JAVA里使用JWT 引入依赖 JWT Service 生成JWT 解码JWT ...
- spring boot:用redis+lua实现基于ip地址的分布式流量限制(限流/简单计数器算法)(spring boot 2.2.0)
一,限流有哪些环节? 1,为什么要限流? 目的:通过对并发请求进行限速或者一个时间单位内的的请求进行限速,目的是保护系统可正常提供服务,避免被压力太大无法响应服务. 如果达到限制速率则可以采取预定的处 ...
- 【分布式架构】--- 基于Redis组件的特性,实现一个分布式限流
分布式---基于Redis进行接口IP限流 场景 为了防止我们的接口被人恶意访问,比如有人通过JMeter工具频繁访问我们的接口,导致接口响应变慢甚至崩溃,所以我们需要对一些特定的接口进行IP限流,即 ...
- 如何利用redis来进行分布式集群系统的限流设计
在很多高并发请求的情况下,我们经常需要对系统进行限流,而且需要对应用集群进行全局的限流,那么我们如何类实现呢. 我们可以利用redis的缓存来进行实现,并且结合mysql数据库一起,先来看一个流程图. ...
- 高并发之API接口限流
在开发高并发系统时有三把利器用来保护系统:缓存.降级和限流 缓存 缓存的目的是提升系统访问速度和增大系统处理容量 降级 降级是当服务出现问题或者影响到核心流程时,需要暂时屏蔽掉,待高峰或者问题解决后再 ...
- 小白也能看懂的Redis教学基础篇——做一个时间窗限流就是这么简单
不知道ZSet(有序集合)的看官们,可以翻阅我的上一篇文章: 小白也能看懂的REDIS教学基础篇--朋友面试被SKIPLIST跳跃表拦住了 书接上回,话说我朋友小A童鞋,终于面世通过加入了一家公司.这 ...
- 使用redis调用lua脚本的方式对接口进行限流
java端实现: //初始化一个redis可执行的lua DefaultRedisScript<List> defaultRedisScript = new DefaultRedisScr ...
- [Kong] key-auth实现对API请求的密钥认证
目录 1. 配置密钥验证插件 2. 确认插件配置正确 3. 创建cunsumer 4. 给cunsumer提供关键凭证 5. 验证 6. 小结 [前言]: 下面我们将配置key-auth插件以向服务添 ...
- KNN算法实现对iris数据集的预测
KNN算法的实现 import pandas as pd from math import dist k = int(input("请输入k值:")) dataTest = pd. ...
- 基于.net的分布式系统限流组件(限流算法:令牌算法和漏斗算法)
转载链接:https://www.cnblogs.com/vveiliang/p/9049393.html 1.令牌桶算法 令牌桶算法是比较常见的限流算法之一,大概描述如下: 1).所有的请求在处理之 ...
随机推荐
- java_web----1
一.HTML 1.网页的构成 结构:HTML 超文本标记语言 标签语言 标签写法: <标签名> </标签名> <标签名/> 表现:CSS 行为:JavaScrip ...
- api进阶Day2(低级流)文件流的输出流、读取流。向文件中写入文本数据、读取文件中的字符串、用lambda表达式创建文件过滤器。
文件流:输出流: package io; import java.io.FileNotFoundException; import java.io.FileOutputStream; import j ...
- hdu:排列组合(指数型母函数)
Problem Description有n种物品,并且知道每种物品的数量.要求从中选出m件物品的排列数.例如有两种物品A,B,并且数量都是1,从中选2件物品,则排列有"AB",&q ...
- 【随笔】Tomcat部署图片服务器Server.xml配置记录
在tomcat应用conf/server.xml文件的标签中添加下面内容: <Service name="imageService"> <!--分配8089端口 ...
- python,数据类型和变量,数据类型和变量,集合,字符串拼接
可不可变: 可变:列表,字典 不可变:字符串,数字,元祖 访问顺序: 直接访问:数字 顺序访问:字符串,列表,元祖 映射:字典 存放元素个数 容器类型:列表,元祖,字典 原子:数字,字符串 集合 1. ...
- C/C++ 数据结构顺序栈的基本操作实现
#include <iostream> #include <Windows.h> using namespace std; #define MAXSIZE 6 //顺序栈的实现 ...
- 我是如何被我的c++大作业榨干的
手把手教你用git上传项目到GitHub(图文并茂,这一篇就够了),相信你一定能成功!! - 知乎 (zhihu.com) C++ 类对象数组_Slience_Perseverance的博客-CSDN ...
- SQL语句用法总结
use quan56_goods; 使用数据库 show tables; 展示数据表 模糊查询 select * from tb_brand where name like '%林%'; 顺序 书写顺 ...
- C++编码注意事项
1. vector,string不能按位赋值(vector用push_back, string用重载"+"号)
- Python从零到壹丨详解图像平滑的两种非线性滤波方法
摘要:本文将详细讲解两种非线性滤波方法中值滤波和双边滤波. 本文分享自华为云社区<[Python从零到壹] 五十六.图像增强及运算篇之图像平滑(中值滤波.双边滤波)>,作者: eastmo ...