Redis 使用场景详解(六)—— 分布式限流

面试官:小伙子,你的代码为什么这么丝滑?

前言

随着互联网的发展和普及,越来越多的应用程序需要处理海量的请求,而这些请求来自于各种终端设备以及各种不同的用户。如何对这些请求进行管理和限制,防止服务器被攻击和压垮,成为了前端开发中必须重视的问题之一。

限流是一种有效的保护机制,其基本原理是限制一定时间内的请求频率和数量。在分布式系统中,限流变得更加复杂,因为需要考虑到多个节点的数据同步和协调。而 Redis 作为一种高性能、可靠的缓存和消息队列数据库,在分布式系统中实现限流具有很高的容错性和可靠性。

本篇文章将详细讲解 Redis 实现分布式限流的方法,包括流量控制算法、实现原理、具体应用场景和示例代码等。

流量控制算法

流量控制算法是限流的核心,其作用是控制系统的请求流量,保证系统在高负载情况下能够正常运行。常见的流量控制算法有如下几种:

计数器限流

计数器限流是一种简单、直接的限流方式,其原理是在一定时间内(如 1 秒钟)限制请求的数量。在 Redis 中,可以使用 INCR 命令实现计数器限流,具体流程如下所示:

  1. 当一个新的请求到来时,通过 INCR 命令将计数器加一;
  2. 如果计数器的值超过了设定的阈值,则将请求拒绝,否则继续处理请求;
  3. 当计数器的超时时间到了以后,将其自动清零,等待下一轮的请求。

计数器限流的优点是实现简单、易于维护,但是也存在一些缺陷。例如,当请求流量非常大时,可能无法满足系统的需求;同时,计数器限流没有考虑请求的复杂性和优先级,容易出现误判和漏判等问题。

漏桶限流

漏桶限流是一种比较稳定和可靠的限流算法,其原理是将请求放入一个桶中,然后按照设定的速率从桶中流出。在 Redis 中,漏桶可以使用 ZSET 数据类型实现,具体流程如下所示:

  1. 将每个请求放入 ZSET 中,并按照时间戳排序;
  2. 每次从 ZSET 中取出请求并处理,直到桶中请求的数量达到设定的阈值;
  3. 在一定时间间隔内,桶中请求的数量是按照设定的速率流出的;
  4. 当请求流量较大时,请求进入桶中,等待处理。

漏桶限流的优点是流量控制比较精确,而且可以设置优先级。缺点是相对比较复杂,容易出现错误和漏洞。

令牌桶限流

令牌桶限流是一种经典、优秀的流控算法,应用广泛,其原理是在设定的时间间隔内,按照一定的速率产生令牌,每次请求需要消耗一个令牌,如果没有令牌则将请求拒绝。在 Redis 中,可以使用 ZSET 数据类型实现令牌桶限流,具体流程如下所示:

  1. 在时间间隔中产生固定数量的令牌,并将其放入 ZSET 中;
  2. 处理请求时,从 ZSET 中取出一个令牌,如果没有令牌则将请求拒绝;
  3. 每次请求完成后,在 ZSET 中增加一个新的令牌。

令牌桶限流的优点是实现比较简单、容易维护、容错性强,而且能够适应各种请求的流量大小和复杂度。缺点是需要耗费一定的计算资源和存储空间,同时如果算法设计不合理,则可能影响系统的响应速度和处理效率。

实现原理

从流控算法的角度来看,Redis 实现分布式限流的方法包括两个方面,一是在 Redis 中存储流量数据,并使用计数器、漏桶或令牌桶等算法进行流量控制;二是通过分布式锁、主从复制和集群等技术,实现多个 Redis 节点之间的数据同步和协调,保证限流算法的正确性和可靠性。

在 Redis 中,实现分布式限流常用的数据类型有 HashListZSET 等,其中 ZSET 数据类型比较适合实现计数器、漏桶和令牌桶。具体来说,计数器限流可以通过 INCR 命令实现,漏桶和令牌桶限流可以通过 ZADDZRANGEZREM 命令实现。

对于分布式数据同步和协调的问题,Redis 提供了多种方案,例如使用 SETNX 命令实现互斥锁,使用 WATCHMULTIEXEC 命令实现事务,使用 Pub/Sub 实现消息发布和订阅等。同时,Redis 支持多种部署方式,包括单节点、主从复制和集群等,可以根据业务需求进行选择和配置,保证系统的高可用和容错性。

应用场景

分布式限流在实际应用中有着广泛的应用场景,包括 Web 应用、移动应用、物联网应用等。常见的应用场景有如下几种:

Web 应用

在 Web 应用中,限制请求的并发数量和请求频率是保证系统稳定和可靠的重要措施。例如,对于登录、注册、支付等敏感操作,需要限制并发请求数量和请求频率,防止恶意攻击和数据泄露。另外,对于热门商品、活动销售等场景,也需要进行流量控制,避免过度消耗系统资源。

移动应用

在移动应用中,限制请求的数据量和请求频率,可以有效地优化用户体验和设备性能。例如,对于用户定位、社交推荐、在线游戏等应用,需要获取大量的用户数据,并进行存储和分析。为了保护用户隐私和提高设备响应速度,需要对这些请求进行限流和流量控制。

物联网应用

在物联网应用中,限制设备请求和数据上传的频率和数量,可以有效地确保系统的稳定性和可靠性。例如,对于环境监测、工业控制、车联网等场景,需要对物理设备进行流量控制,防止系统崩溃或数据混乱。

示例代码

以下示例代码展示了如何在 Redis 中使用令牌桶算法实现分布式限流:

------ -----
------ ----

----- -------------------------
    --- -------------- ----- ----- --------- ------------ ------------
        ----------------- - ---------------------- ---------- ------------------
        ---------------- - -----------
        --------------- - ----------

    --- --------------------
        ------ --------------- - -----

    --- ------------------ ---- -----------
        --------------------------- ----------- -----------
        --------------------------------------- ------- --------- - ---------------- - -----

    --- --------------- -----
        ------ ------------------------------

    --- --------------- -----
        ----------- - ----------------------------- ------- -------
        -- ----------- - -----------------
            ----------------- - --------------------
            ---------------------- ------------------
        ------ -------------------

    --- ---------------------
        ------ -------- - ----------------

    --- -------------- -----
        ---------- - ---------------------
        ----- -----
            ----- - -------------------
            -- ------
                ------ ----
            --------------------- - -------

在上述代码中,使用 ZSET 实现令牌桶算法,使用 zaddzpopminzcount 命令分别实现创建令牌、取出令牌和查询令牌数量。对于分布式限流,需要对每个请求对应的 key 进行控制,遵循公平和优先级的原则。预设的 bucket_sizetoken_rate 分别表示令牌桶的大小和令牌产生的速率。

最后,在 throttle 方法中调用 get_token 方法创建令牌,若令牌数量大于等于请求需求,则返回令牌,否则等待一定的时间后重新获取令牌。

结论

分布式限流作为一种重要的保护机制,对于保证系统的安全性和稳定性具有重要意义。在实际应用中,可以根据业务需求和系统特性选择合适的流控算法和数据存储方式,实现分布式限流。同时,需要注意分布式数据同步和协调的问题,并进行合理的部署和配置,以确保限流算法的正确性和可靠性。

来源:JavaScript中文网 ,转载请联系管理员! 本文地址:https://www.javascriptcn.com/post/670a6501d91dce0dc8811a7a


猜你喜欢

  • Custom Elements 如何进行版本管理

    Custom Elements 是一项可在网页上创建自定义 HTML 标签的技术,其实现和使用都很简单,但要将其应用于生产环境并进行版本管理则需要一些特殊的技巧。本文将介绍如何在 Custom Ele...

    5 天前
  • Express.js 中使用 WebSocket 实现视频流传输的方法和最佳实践

    介绍 随着现代网络技术的不断发展,视频已经成为人们日常生活中的一部分。在线视频服务的流行使得视频流传输成为了前端开发中的一个非常重要的问题。WebSocket 是一个流行的技术,它可以帮助前端开发者解...

    5 天前
  • ES11 BigInt 类型使用实践

    ES11 在 JavaScript 语言标准上增加了一种新的数据类型:BigInt。BigInt 用于表示任意精度的整数,可以超出 JavaScript 中 Number 类型的安全整数范围,方便开发...

    5 天前
  • 使用 Headless CMS 集成微信公众号的技术实现方案

    引言 微信公众号是现在互联网上非常流行的一种社交平台,很多企业和开发者都会利用微信公众号来进行宣传和交流。而随着前端技术的发展,利用前端技术来实现微信公众号的集成也成为了一种非常有趣的尝试。

    5 天前
  • 如何在 Node.js 中使用 Morgan 进行日志记录

    在编写 Web 应用程序时,记录应用程序行为并对其进行分析非常重要。Node.js 中的 Morgan 是一个强大的日志记录中间件,它可以轻松地捕获 HTTP 请求和响应的详细信息。

    5 天前
  • 使用 Chai.js 和 Mocha.js 测试 JavaScript 异步代码

    前端开发离不开 JavaScript,而测试是保证代码质量的重要方法。在测试过程中,我们需要验证异步代码的正确性,这时就需要用到 Chai.js 和 Mocha.js。

    5 天前
  • 如何在 PWA 应用中使用 Web App Manifest 的高级特性

    什么是 PWA 应用 PWA 的全称为 Progressive Web App,是在 Web 技术的基础上打造的移动应用的一种新型方式。PWA 应用可以提供与原生应用相同的用户体验,但是基于 Web ...

    5 天前
  • SSE 示例代码解读及优化:面向模式的变化

    随着互联网的发展,实时性越来越成为前端开发项目的核心需求。Server-Sent Events(SSE),即服务器推送事件,是一种新兴的技术,可以帮助前端实现长轮询、流媒体传输和事件通知等功能。

    5 天前
  • Docker 容器中服务进程频繁退出的解决方法

    前言 在使用 Docker 部署服务时,有时会遇到服务进程频繁退出的问题。这个问题通常是由于容器中的进程没有正常启动或遇到错误退出所导致的。如果不及时修复,这些频繁退出的问题可能会影响服务的可用性和稳...

    5 天前
  • Jest 测试中的 Mock API 技术解析

    在前端开发中,测试是不可或缺的一部分。而 Jest 是一种广泛使用的测试框架,它支持 Mock API 技术,在测试中可以模拟出接口的返回结果,实现快速测试、完整覆盖和准确调试的目标。

    5 天前
  • 如何使用 Next.js 发送电子邮件

    在构建 Web 应用程序时,电子邮件是一个重要的功能,可以让您的应用程序与用户进行交互和通信。在本文中,我们将介绍如何使用 Next.js 框架来发送电子邮件。 准备工作 在开始之前,确保您已经安装了...

    5 天前
  • 解决在 Hapi.js 中的 “ERR_INVALID_ARG_TYPE” 错误

    Hapi.js 是一个现代化的 Node.js 框架,它提供了强大的构建 Web 应用的基础设施。不过,在使用 Hapi.js 开发过程中,你可能会遇到 “ERR_INVALID_ARG_TYPE” ...

    5 天前
  • Custom Elements 在 Flutter 中的应用

    在最新的 Flutter 版本中,开发者可以通过 Custom Elements 来快速地创建可复用的 Flutter 组件。这项新特性在构建大规模的跨平台应用程序时非常有用,因为它可以大幅减少代码重...

    5 天前
  • Fastify 应用程序中的分组路由详解

    Fastify 是一个快速、低开销的 Web 框架,它支持异步并发请求处理。在 Fastify 中,您可以使用路由将 URL 匹配到处理程序。而分组路由是一种组织路由的有效方式,使得应用程序更加模块化...

    5 天前
  • Web Components 中常见的异步操作技巧与优化建议

    随着 Web 组件在 Web 开发中的普及,越来越多的开发者开始开发和使用 Web 组件。Web 组件是一种封装了 HTML、CSS 和 JavaScript 的独立模块,可以扩展 HTML 的语义和...

    5 天前
  • CSS Grid 布局: 使用顺序与显示创建媒体板式

    前言 在前端开发中,网格布局已经成为最常用的布局方式之一。而 CSS Grid 布局就是现在最流行的网格布局方式。它为开发人员提供了丰富的功能,可帮助他们轻松地创建各种布局,从简单的网格到复杂的多列布...

    5 天前
  • ES10 之 Symbol,能为 JavaScript 增加新的值类型

    ES10之Symbol,能为JavaScript增加新的值类型 介绍 Symbol是一个ES6引入的全新数据类型,是JavaScript的第七种原始数据类型。ES10进一步对Symbol进行了增强,使...

    5 天前
  • Express.js 中使用 Jest 进行单元测试的技巧和最佳实践

    简介 在前端开发中,单元测试是非常重要的一环。在 Express.js 中,我们可以使用 Jest 来进行单元测试,它是一个非常流行的 JavaScript 测试框架。

    5 天前
  • 如何在 React 中使用 Enzyme 进行渲染测试?

    Enzyme 是一个 React 应用程序的 JavaScript 测试实用程序库。它由 Airbnb 开发,使得在实施单元测试和集成测试时,可以更加轻松地访问和操作 React 组件的输出。

    5 天前
  • JavaScript 从 ES6 到 ES10 的异步编程详解

    JavaScript 从 ES6 到 ES10 的异步编程详解 在前端开发中,异步编程是非常重要的。它可以提高页面响应速度,避免页面出现卡顿现象,提高用户体验。而 JavaScript 自 ES6 版...

    5 天前

相关推荐

    暂无文章