深入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);//返回存放的数据条数 ...
随机推荐
- 关于Android的Build类——获取Android手机设备各种信息
经常遇到要获取Android手机设备的相关信息,来进行业务的开发,比如经常会遇到要获取CPU的类型来进行so库的动态的下载.而这些都是在Android的Build类里面.相关信息如下: private ...
- ArrayAdapter、SimpleAdapter和BaseAdapter示例代码
import android.content.Context; import android.util.Pair; import android.view.View; import android.v ...
- docker_usb开发软件部署
1.docker镜像包 (备注:61提供,带桌面版本) rayosx2.0.2.tar 2.paho-mqtt dnf install git -y git clone https://github ...
- Java 关于容器集合等数据结构详情图解,一目了然
建议把图片下载下来保存之,网页展示不开... watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvY3NtX3F6/font/5a6L5L2T/fontsize/ ...
- Node.js meitulu图片批量下载爬虫1.02版
以前版本需要先查看网页源码,然后肉眼找到图片数量和子目录,虽说不费事,但多少有点不方便. 于是修改了一下,用cheerio自己去找找到图片数量和子目录,只要修改页面地址就行了.至此社会又前进了一步. ...
- MyEclipse图表工具Birt的使用技巧(三)--连接webservice数据源
Web Services 技术是一套标准.它定义了应用程序怎样在Web上实现互操作. 用户能够使用不论什么语言.在不同的平台下编写Web Services.然后通过Web Services 的标准来对 ...
- ajax--百度百科
AJAX即“Asynchronous Javascript And XML”(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术. AJAX = 异步 JavaScript和 ...
- 关于继承Fragment后重写构造方法而产生的错误
在android开发中.写了一个关于继承Fragment的类时,假设有重载构造函数时.会提示"Avoid non-default constructors in fragments: use ...
- C# Soap调WebService
public class WebServiceHelper { /// <summary> /// Soap协议Post方法 /// </summary> /// <pa ...
- PV、UV、GMV
原文地址:电商术语:客单价.UV.PV.转化率.销售额作者:馨闻莲博 UV(独立访客):Unique Visitor,访问您网站的一台电脑客户端为一个访客.00:00-24:00内相同的客户端只会被计 ...