Redis 缓存穿透问题分析与解决方案

缓存是提高网站性能的重要手段,而 Redis 作为一款高性能的内存数据库,被广泛应用于网站开发中。然而,伴随着缓存操作的增多,却也出现了一个被称为“缓存穿透”的难题。

所谓缓存穿透,指的是一些恶意攻击者通过构造一些不存在于数据库中的 key,频繁地向 Redis 中查询,从而造成缓存雪崩的严重后果。本文将从原理、危害及解决方案三个方面,详细分析 Redis 缓存穿透问题,并给出相应的解决方案。

Redis 缓存穿透的原理

Redis 是一款 key-value 数据库,每个 key 对应一个 value,并将数据存储在内存中,因此速度极快。因此,网站开发人员习惯于通过缓存将热点数据放在 Redis 中,以快速响应客户端请求。

而当客户端向 Redis 发起请求时,Redis 会检查请求中的 key 是否存在,如果存在则返回对应的 value,如果不存在则将请求转发到数据库中查询。然而,在缓存穿透攻击的情况下,攻击者会构造一些不存在于数据库中的 key,频繁向 Redis 发送请求,这时 Redis 会将全部请求都转发到数据库中,导致查询数据库的次数急剧增加,从而降低了网站的性能。

缓存穿透的危害

缓存穿透可能会导致以下几种危害:

  1. 浪费大量的数据库资源。
  2. 降低网站性能,导致网站响应时间加长。
  3. 由于频繁地访问数据库,可能会导致数据库崩溃,从而引发连锁反应,导致网站瘫痪。

因此,我们必须要采取有效的解决方案,避免缓存穿透问题的出现。

解决方案

方案一:布隆过滤器

布隆过滤器(Bloom Filter)是一种快速且占用空间较小的数据结构,常用于判断一个元素是否在集合中。布隆过滤器中存储了一些 hash 函数,通过这些 hash 函数将元素映射到一个二进制向量中,并将相应位置标记为 1。当一个元素进入布隆过滤器中时,它的每个 hash 值被映射到二进制向量上,将相应的位置标记为 1。在查询元素是否在集合中时,将元素的 hash 值映射到二进制向量上,查看相应的位置是否都为 1,如果都为 1,则说明该元素可能存在于集合中。

在使用布隆过滤器时,我们需要在 Redis 中建立一个布隆过滤器,每当一个请求到达时,先将该请求的 key 传入布隆过滤器中验证,如果不存在则说明该 key 不存在于 Redis 中,直接返回 null 值即可。

示例代码如下:

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

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

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

方案二:缓存空对象

由于 Redis 中不存在的 key 返回 null 值,因此我们可以在 Redis 中存储一个空对象,表示此 key 查询过但查询结果为空。

示例代码如下:

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

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

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

方案三:缓存过期时间

我们可以为 Redis 中的每个 key 设置一个过期时间,当一个不存在于数据库中的 key 被查询时,Redis 会将其缓存一段时间(一般为几分钟),过了有效期之后再查询数据库中是否存在。

示例代码如下:

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

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

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

总结

缓存穿透是一个非常棘手的问题,我们需要通过布隆过滤器、缓存空对象、缓存过期时间等多种方式来避免缓存穿透问题的发生。然而,我们也不能一开始就将信誉度掏空,而是需要通过黑名单、IP 屏蔽等方式来避免恶意攻击者的入侵,从而保证网站的正常运行。

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


猜你喜欢

  • 使用 Jest 测试 Vue Router 的方法

    Vue Router 是 Vue.js 的官方路由管理器,它可让您构建基于 Vue.js 的单页应用程序(SPA)。单页应用程序的路由管理是前端开发中的重要问题之一。

    1 年前
  • # ES10 之 Destructuring 与 Rest Parameters

    ES10 之 Destructuring 与 Rest Parameters ES10,即 ECMAScript 2019,是 JavaScript 的最新版本之一。

    1 年前
  • Custom Elements 如何支持多语言

    在前端开发中,我们经常用到自定义元素(Custom Elements)来扩展 HTML 标签,使其拥有自定义的行为和样式。在多语言环境中,我们需要让自定义元素也支持多语言,以满足用户不同语言环境的需求...

    1 年前
  • 如何在 Fastify 应用程序中处理 QueryString 参数

    在前端开发中,我们经常会使用查询字符串(QueryString)来获取 URL 中的参数值。在 Fastify 应用程序中,处理 QueryString 参数也同样重要。

    1 年前
  • 如何在 React Native 中使用 Enzyme 测试子组件?

    React Native 是 Facebook 推出的一款跨平台的移动应用开发框架,许多使用 React Native 开发的应用都有复杂的组件结构和嵌套关系。我们如果想要对这些组件进行测试,就需要使...

    1 年前
  • ES11 BigInt 详解

    JavaScript是一种动态语言,当前最新版本为ES11。在这个版本中,BigInt成为了ES11中的新增特性之一。BigInt提供了一种新的数字类型,用于表示更大范围的数字,可以解决在JavaSc...

    1 年前
  • 活学活用 ES6 多维数组(Array)之用法篇 (1)

    在前端开发中,数组是经常被使用的数据类型。ES6 加入了许多新的特性来方便我们使用数组。其中,多维数组的应用更是不容忽视的一部分。在本文中,我们将深入学习 ES6 多维数组的常见用法。

    1 年前
  • # Web Components 中的高性能渲染问题优化手段详解

    Web Components 中的高性能渲染问题优化手段详解 前言 Web Components 是一种新的 Web 技术,可以让开发者创建自己的 HTML 标签,并在多个项目之间重复使用。

    1 年前
  • ECMAScript 2021 中的 Logical Assignment Operators:如何更好地管理变量赋值

    前端开发中,变量的管理是一个非常重要的问题。ECMAScript 2021 中加入的 Logical Assignment Operators 可以帮助我们更好地管理变量赋值。

    1 年前
  • JavaScript 中防止事件冒泡和默认事件的方法

    在前端开发中,常常需要对页面上的元素进行事件绑定和处理。但是,有些情况下,我们希望阻止事件的冒泡,或者取消事件的默认行为,避免出现意外情况。本文将介绍 JavaScript 中防止事件冒泡和默认事件的...

    1 年前
  • 在 Node.js 中使用 ES6 语法解构赋值的基本用法

    随着前端技术的发展,ES6(ECMAScript 2015)在各个领域得到了广泛的应用。其中解构赋值是 ES6 中的一个非常常用的特性,它可以让你方便快捷地对数组和对象中的值进行取出和赋值。

    1 年前
  • Socket.io 实现的即时聊天室实践

    Socket.io 是一个实现了 WebSocket 协议的 JavaScript 库,能够轻易地在前端和后端之间建立即时通信连接。这里,我们将介绍 Socket.io 的一些基本知识,并通过实例的形...

    1 年前
  • MongoDB 中的安全管理方法详解

    作为一名前端工程师,了解数据库的基本使用和安全管理方法是必不可少的。MongoDB 作为 NoSQL 数据库的代表,其开放性和灵活性让它受到了越来越多的关注。但是 MongoDB 的安全性一直是人们所...

    1 年前
  • 用 CSS Flexbox 布局解密网页底部浮动层

    在现代网页设计中,底部浮动层已经成为了很多网站和应用的标配之一。它不仅能够提升用户体验,还能够增加页面的功能性和美观性,可以说是一个非常实用的设计元素。 但是在实际开发中,底部浮动层的实现并不是那么容...

    1 年前
  • 使用 Deno 构建一个简单的在线教育网站

    在线教育成为了近年来的热门话题,面对这个庞大的市场,如何构建一个稳定且易于扩展的网站是每个技术人员必备的技能。本文将介绍如何使用 Deno 构建一个简单的在线教育网站。

    1 年前
  • Vue.js 项目中如何使用第三方 UI 组件库?

    Vue.js 是一个流行的 JavaScript 前端框架,它简单易学且功能强大。不仅如此,Vue.js 还支持使用第三方 UI 组件库,使得开发者更加方便快捷地创建出美观的用户界面。

    1 年前
  • Vue SPA 应用中如何进行懒加载

    随着单页应用越来越流行,懒加载也成了应用中不可或缺的一部分。Vue.js 作为现在最流行的前端框架之一,提供了非常简单的 API 来实现懒加载。不过,这个过程并不是那么简单,这篇文章将会介绍如何在 V...

    1 年前
  • 重构 RESTful API 的原则和技巧

    前言 RESTful API 在 Web 开发中扮演着非常重要的角色。随着时间的推移,一个初始的 API 设计可能会变得混乱、臃肿和难以维护。重构 API 可以帮助我们消除这些问题,使它更加稳定、易用...

    1 年前
  • 使用 Cypress 测试框架进行移动端自动化测试

    前言 对于前端开发,自动化测试是非常重要的一环。随着移动端的发展,移动端自动化测试也逐渐成为前端开发不可或缺的一部分。在这一领域,Cypress 测试框架是一款很受欢迎的工具。

    1 年前
  • 为视力较差者改进 Web 体验

    随着互联网的飞速发展,Web 应用日益普及,已经成为人们日常生活中不可或缺的一部分。然而,由于 Web 设计并不是为所有人都设计的,一些视力受损的用户可能会遇到一些困难和挑战。

    1 年前

相关推荐

    暂无文章