问题

在许多应用中,对昂贵的资源的访问必须加以限制,此时速率限制是必不可少的。许多现代网络应用程序在多个进程和服务器上运行,状态需要被共享。一个理想的解决方案应该是高效、 快捷的,而不是依赖于被绑定到特定客户端的单个应用程序服务器(由于负载平衡) 或本身持有任何状态。

解决方案

实现这一目标的一个简单有效的方法就是使用 Redis, 它有很多有用的数据结构和功能, 尽管实现速率限制只需要2个功能用: 一、在某个具体的键值上递增一个整数,二、给这个键值设置过期时间。

因为redis 有个单一的事件循环系统 (每个人每次在同一个时间只能执行一个操作),这是个原子操作, 也就是说无论有多少个客户端同时交互操作,对于同一个键值总有一个确定的数值。

这在对同一个资源进行多个速率限制的情况下通常是有利的, 因为这允许少量的破裂,以及更长的期限限制。例如每秒钟请求3次,没分钟请求20次。因为每个限制都是相对独立的,这就需要与其它限制分开进行单独的递增。

因为速率限制通常用在响应时间比较重要的资源(比如网页应用),所以尽量缩短速率限制的使用时间是非常有必要的。redis的最基本的应用就是发出命令,等待响应,然后发出另一个命令,如此往复。 这个花费是昂贵的,因为需要通过网络在应用程序和redis服务器之间多次往返。由于在这个用例中,没有命令依赖其它命令的执行结果,这使得redis的一个叫做流水线技术的使用成为可能。这就是客户端缓存所有redis请求,然后把这写请求发送给redis,redis一次性返回所有的结果。

Redis不会维护客户端需要的限制的,因为redis会根据客户端设置的过期时间删除旧的记数。这消除了客户端统筹协调的需要,和删除竞争条件的可能性。

The Code import redis import time

def rate_limit_check(r, key, limits): period_lengths = [[0] for _ in sorted(limits.items())] period_limits = [[1] for _ in sorted(limits.items())] pipe = r.pipeline() for period_length in period_lengths: current_period = int(time.time() / period_length) redis_key = 'rate_limit:{key}:{period_length}:{current_period}'.format(key=key, period_length=period_length, current_period=current_period) pipe.incr(redis_key).expire(redis_key, period_length*3) return not any(hits > period_limit for period_limit, hits in zip(period_limits, pipe.execute()[::2]))

if name == 'main': r = redis.Redis() print rate_limit_check(r, '127.0.0.1', {1: 3, 60: 20}) {1: 3, 60: 20} 意味着每秒钟3次的命中率是允许的,在任何限制下,都允许20次的命中。'127.0.0.1'在这里用作键值,尽管在真实的情况下,可能作为IP地址。更高级的用例将有一个全应用程序的速率限制,键值只有客户端的IP地址,以及一个为昂贵的终结点设置的特定终结点限制,这将用到客户端的IP地址和终结点,例如127.0.0.1+/login/。这些限制可以独立地设置。

return rate_limit_check(r, '127.0.0.1', {1: 3, 60: 20}) and rate_limit_check(r, '127.0.0.1+/login/', {1: 2, 60: 5}) 这是一个用Python写的例子,它可以简单地移植到任何语言,只要这门语言包含Redis客户端库。

使用 Redis 实现分布式速率限制相关推荐

  1. 基于redis的分布式任务管理

    业务背景 系统中有各种定时任务,需要满足以下要求: 定时任务需要能够动态增删改查 需要能够设置任务的有效时间范围(只在此范围内执行) 任务执行周期需要能够灵活配置 需要能够轻松接入各种任务实现 需要能 ...

  2. Redis:使用Redis的分布式锁

    在许多环境中不同进程必须以互斥方式使用共享资源进行操作时,分布式锁是非常有用的原语. 有许多库和博客文章描述了如何使用Redis实现DLM(分布式锁管理器)(Distributed Lock Mana ...

  3. Redlock 算法:Redis 实现分布式锁(译)

    先介绍两个概念 Safety Properties, 在程序运行中不会进入非预期的状态(如非法调用参数, 数组下标越界等运行错误) Liveness Properties, 在程序运行中预期状态一定会 ...

  4. 手写基于redis实现分布式限流器-pdlr

    一.限流器介绍 简单来讲,限流器就是控制流量访问速率的一种机制,在短时间内大量流量访问时,不至于使服务器崩溃.比如,一分钟之内,如果限制1000个请求可以访问,当第1001个请求到达时,请求被拒绝(这 ...

  5. Redis实现分布式限流(学习笔记

    Redis实现分布式限流(学习笔记2022.07.09) 前言: 以下实现都是基于: spring-boot-starter-web + spring-boot-starter-data-redis ...

  6. 基于Redis的分布式限流详解

    前言 Redis除了能用作缓存外,还有很多其他用途,比如分布式锁,分布式限流,分布式唯一主键等,本文将和大家分享下基于Redis分布式限流的各种实现方案. 一.为什么需要限流 用最简单的话来说:外部请 ...

  7. 170222、使用Spring Session和Redis解决分布式Session跨域共享问题

    使用Spring Session和Redis解决分布式Session跨域共享问题 原创 2017-02-27 徐刘根 Java后端技术 前言 对于分布式使用Nginx+Tomcat实现负载均衡,最常用 ...

  8. 基于 Redis 实现分布式锁思考

    以下文章来源方志朋的博客,回复"666"获面试宝典 来源:blog.csdn.net/xuan_lu/article/details/111600302 分布式锁 基于redis实 ...

  9. Redis实现分布式锁的深入探究

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试文章 一.分布式锁简介 锁 是一种用来解决多个执行线程 访问共享资源 错 ...

最新文章

  1. C# ref和out关键字
  2. Java序列化bean保存到本地文件中
  3. 长沙网络推广教你如何在网站优化中让URL标准化?
  4. oracle 11g r2配置文件,Oracle 11g R2 常用配置与日志的文件位置
  5. POJ 2312 Battle City 优先队列+BFS
  6. [NodeJs] 如果发现node_modules中有个模块代码有bug,你该怎么办?
  7. 把一张合成图分拆出各个小图
  8. Golang笔记—文件操作
  9. Android开发 使用HBuilder的缓存方法
  10. 16.1 调色板的使用
  11. 故障模块名称kernelbase.dll_OBDII(OBD2)故障码库P0700P0799
  12. matlab神经网络工具箱的使用
  13. h5课件制作_湘潭H5课件制作
  14. 华为机试练习(七)书籍叠放问题
  15. 云计算架构中的Iaas、Paas、SaaS详解
  16. 五年IT五股东风 吹奏一曲SaaS“东风破”
  17. Word文件解除限制编辑
  18. pythoncharm中文版_Pycharm2020中文版下载
  19. 爬虫第四篇-爬虫对网站改版快速解决思路
  20. Receptive Field(感受野)的理解

热门文章

  1. mybaits四-1:增删改查的实现
  2. Web的诞生和网络基础 | 读《图解HTTP》
  3. capistranorb
  4. ObjC load与initialize 简析
  5. matlab练习程序(图像旋转,最邻近插值)
  6. Nginx负载均衡和反向代理
  7. maven学习(中)- 私服nexus搭建
  8. Ubuntu显示隐藏文件和文件夹
  9. Struts2文件上传
  10. iis 服务器出现server too busy!