深入Redis漏斗限流
漏斗限流是最常用的限流方法之一,漏斗流水的速率大于灌水的速率,漏斗就永远装不满,反之水就会溢出。
所以漏斗的剩余空间就代表当前行为可以持续进行的数量,水流出的速率代表系统允许该行为的最大频率。
import time
class Funnel:
def __init__(self, capacity, leaking_rate):
self.capacity = capacity # 漏斗容量
self.leaking_rate = leaking_rate # 流出速率
self.left_quota = capacity # 漏斗剩余空间
self.leaking_ts = time.time() # 上一次漏水时间
def make_space(self):
now_ts = time.time()
delta_ts = now_ts - self.leaking_ts # 距离上一次漏水过去了多久
delta_quota = delta_ts * self.leaking_rate # 腾出的空间
if delta_quota < 1: # 腾的空间过小等待下一次
return
self.left_quota += delta_quota # 增加剩余空间
self.leaking_ts = now_ts # 记录漏水时间
if self.left_quota > self.capacity: # 剩余空间不得高于容量
self.left_quota = self.capacity
def watering(self, quota):
self.make_space()
if self.left_quota >= quota: # 判断剩余空间是否足够
self.left_quota -= quota
return True
return False
funnels = {} # 所有的漏斗
def is_action_allowed(
user_id, action_key, capacity, leaking_rate):
key = '{}:{}'.format(user_id, action_key)
funnel = funnels.get(key)
if not funnel:
funnels[key] = Funnel(capacity, leaking_rate)
return funnel.watering(1)
for i in range(20):
print is_action_allowed('tom', 'reply', 15, 0.5)
make_space方法是漏斗算法的核心,其在每次灌水前都会被调用以触发漏水,给漏斗腾出空间,Funnel占据的空间大小不与行为频率成正比,其空间占用是一个常量。
问题是分布式漏斗算法如何实现?
Funnel类其实就是一个高级字典,那么我们可以利用Redis中的hash结构来存储对应字段,灌水时将字段取出进行逻辑运算后再存入hash结构中即可完成一次行为频度的检测。但这有个问题就是整个过程的原子性无法保证,意味着要用锁来控制,但如果加锁失败,就要重试或者放弃,这回导致性能下降和影响用户体验,同时代码复杂度也升高了,此时Redis提供了一个插件,Redis-Cell出现了。
Redis-Cell
Redis 4.0提供了一个限流Redis模块,名称为redis-cell,该模块提供漏斗算法,并提供原子的限流指令。
该模块只有一条指令cl.throttle,其参数和返回值比较复杂。
> cl.throttle tom:reply 14 30 60 1
1) (integer) 0 # 0表示允许,1表示拒绝
2) (integer) 15 # 漏斗容量capacity
3) (integer) 14 # 漏斗剩余空间left_quota
4) (integer) -1 # 如果拒绝了,需要多长时间后再重试,单位秒
5) (integer) 2 # 多长时间后,漏斗完全空出来,单位秒
该指令意思为,允许用户tom的reply行为的频率为每60s最多30次,漏斗初始容量为15(因为是从0开始计数,到14为15个),默认每个行为占据的空间为1(可选参数)。
如果被拒绝,取返回数组的第四个值进行sleep即可作为重试时间,也可以异步定时任务来重试。
注意事项
由于Redis-Cell是基于Rust语言写的插件,因此在安装插件前要先安装rust。
具体方法看GitHub。
深入Redis漏斗限流的更多相关文章
- 基于Redis的限流系统的设计
本文讲述基于Redis的限流系统的设计,主要会谈及限流系统中限流策略这个功能的设计:在实现方面,算法使用的是令牌桶算法来,访问Redis使用lua脚本. 1.概念 In computer netw ...
- redis之漏斗限流
Redis 4.0 提供了一个限流 Redis 模块,它叫 redis-cell.该模块也使用了漏斗算法,并提供了原子的限流指令.有了这个模块,限流问题就非常简单了.
- Envoy实现.NET架构的网关(五)集成Redis实现限流
什么是限流 限流即限制并发量,限制某一段时间只有指定数量的请求进入后台服务器,遇到流量高峰期或者流量突增时,把流量速率限制在系统所能接受的合理范围之内,不至于让系统被高流量击垮.而Envoy可以通过e ...
- Redis解读(4):Redis中HyperLongLog、布隆过滤器、限流、Geo、及Scan等进阶应用
Redis中的HyperLogLog 一般我们评估一个网站的访问量,有几个主要的参数: pv,Page View,网页的浏览量 uv,User View,访问的用户 一般来说,pv 或者 uv 的统计 ...
- 库存秒杀问题-redis解决方案- 接口限流
<?php/** * Created by PhpStorm. * redis 销量超卖秒杀解决方案 * redis 文档:http://doc.redisfans.com/ * ab -n 1 ...
- 限流(三)Redis + lua分布式限流
一.简介 1)分布式限流 如果是单实例项目,我们使用Guava这样的轻便又高性能的堆缓存来处理限流.但是当项目发展为多实例了以后呢?这时候我们就需要采用分布式限流的方式,分布式限流可以以redis + ...
- 【分布式架构】--- 基于Redis组件的特性,实现一个分布式限流
分布式---基于Redis进行接口IP限流 场景 为了防止我们的接口被人恶意访问,比如有人通过JMeter工具频繁访问我们的接口,导致接口响应变慢甚至崩溃,所以我们需要对一些特定的接口进行IP限流,即 ...
- 分布式限流组件-基于Redis的注解支持的Ratelimiter
原文:https://juejin.im/entry/5bd491c85188255ac2629bef?utm_source=coffeephp.com 在分布式领域,我们难免会遇到并发量突增,对后端 ...
- Redis除了做缓存--Redis做消息队列/Redis做分布式锁/Redis做接口限流
1.用Redis实现消息队列 用命令lpush入队,rpop出队 Long size = jedis.lpush("QueueName", message);//返回存放的数据条数 ...
随机推荐
- 我是如何给discuz模板做语法高亮的/vs code/textmate
本人一直做ASP.NET开发,近期接到任务要用Discuz开发一个社区,第一次接触PHP,PHP灵活的语法,天生的模块化,各种语法糖深深的震惊了我,我从内心深处感受到了PHP是最牛逼的语言!!! 好了 ...
- FSLib.Extension库
FSLib.Extension库是一个用于.NET的扩展函数库,所提供的函数和方法均使用扩展方法引入,包含数以百计的用于日常编写程序时使用的扩展方法. http://www.fishlee.net/s ...
- XAMPP安装与多虚拟目录地址设置
前端开发集成环境-XAMPP 在前端开发中,经常需要进行请求的调试等都需要一个服务器环境,这时类似wamp.XAMPP就是我们最后的选择,集成apache.php.mysql等一应俱全,不需要去单独配 ...
- 微信开发之消息接收与回复--weixin-java-tools
一.前言 在上一篇文章<微信开发之如何使用开发工具--weixin-java-tools>中我给各位介绍了weixin-java-tools,并且介绍了如何使用weixin-java-to ...
- redis深入研究
Redis 设计思路学习与总结 https://cloud.tencent.com/developer/article/1004464 Redis 设计思路学习与总结 下半年利用空余时间研究和分析了部 ...
- 【招聘App】—— React/Nodejs/MongoDB全栈项目:项目准备
前言:最近在学习Redux+react+Router+Nodejs全栈开发高级课程,这里对实践过程作个记录,方便自己和大家翻阅.最终成果github地址:https://github.com/66We ...
- Java Web---登录验证和字符编码过滤器
什么是过滤器? 在Java Web中,过滤器即Filter.Servlet API中提供了一个Filter接口(javax.servlet.Filter).开发web应用时,假设编写的Java类实现了 ...
- 作为Java程序员应该掌握的10项技能
本文详细罗列了作为Java程序员应该掌握的10项技能.分享给大家供大家参考.具体如下: 1.语法:必须比较熟悉,在写代码的时候IDE的编辑器对某一行报错应该能够根据报错信息知道是什么样的语法错误并且知 ...
- opencv提取surf特征点出现的错误
opencv实现surf特征的提取.本来是一个非常easy的代码,结果我执行时却出现了各种错误,以下来谈谈我出现的错误及问题的解决过程. 首先,我把提取surf特征的过程整合成了一个函数,我单独建立一 ...
- Github——Git设置及GitHub的使用
把github上的help. First : 安装:ubuntu 下,终端输入命令: sudo apt-get install git-core git-gui git-doc Next : 设置SS ...