为什么Redis中不建议使用KEYS?

2024-04-19

在Redis中,建议不要使用按键命令 https://redis.io/commands/KEYS。为什么会这样呢?是因为它的时间复杂度是 O(N) 吗?或者是别的什么原因。


我做了下面的实验来证明KEYS命令有多么危险。

当带有 KEYS 的一个命令运行时,其他 KEYS 命令正在等待运行时间。 KEYS 命令的一次运行有两个阶段,第一个阶段是从 Redis 获取信息,第二个阶段是将其发送到客户端。

$ time src/redis-cli keys "*" | wc -l
1450832
real    0m17.943s
user    0m8.341s


$ src/redis-cli
127.0.0.1:6379> slowlog get
1) 1) (integer) 0
   2) (integer) 1621437661
   3) (integer) 8321405
   4) 1) "keys"
      2) "*"

因此,它在 Redis 上运行了 8 秒,然后通过管道传输到“wc”命令。 Redis 在 8 秒内完成了该命令,但“wc”命令需要 17 秒的数据才能完成计算。因此内存缓冲区必须存在至少 17 秒。现在,让我们想象一下网络上的客户端,这些数据也必须发送到客户端。如果我们有 10 个键命令,这些命令将在 Redis 上逐个运行,当第一个命令完成并且下一个命令运行时,第一个命令的结果必须先存储在内存中,然后客户端才会使用它们。这一切都需要内存,所以我可以想象一种情况,第五个客户端正在运行 KEYS 命令,但我们仍然需要保留第一个客户端的数据,因为它们仍然没有通过网络传输。

我们来测试一下。

场景:我们有一个 200M 大小(1000M 物理内存)的 Redis DB,检查一次执行 KEYS 需要多少内存,以及通过网络执行时需要多长时间。然后模拟5个相同的KEYS命令运行,看看是否会杀死Redis。

$ src/redis-cli info memory
used_memory_human:214.17M
total_system_memory_human:926.08M

When run from the same node:
$ time src/redis-cli keys "*" | wc -l
1450832
real    0m17.702s
user    0m8.278s

$ free -m
              total        used        free      shared  buff/cache   available
Mem:            926         301         236          24         388         542
Mem:            926         336         200          24         388         507
Mem:            926         368         168          24         388         475
Mem:            926         445          91          24         388         398
Mem:            926         480          52          24         393         363
Mem:            926         491          35          24         399         352
-> looks like it consumed 190M for the KEYS command

-> 所以,Redis 忙于该命令 8s,但该命令消耗内存 17s。 -> 仅运行一个 KEYS 命令只会阻塞 Redis 8 秒,但不会导致 OOM

让我们(几乎)同时运行 2 个 KEYS 命令(无论如何都会一个接一个地运行)

$ time src/redis-cli keys "*" | wc -l &
$ time src/redis-cli keys "*" | wc -l &

$ free -m
              total        used        free      shared  buff/cache   available
Mem:            926         300         430          24         194         546
Mem:            926         370         361          24         194         477
Mem:            926         454         276          24         194         393
Mem:            926         589         141          24         194         258
Mem:            926         693          37          24         194         154
-> now we used 392M memory for 26s, while Redis is hung for 17s
-> but we still have a running Redis

让我们(几乎)同时运行 3 个 KEYS 命令(无论如何都会一个接一个地运行)

$ time src/redis-cli keys "*" | wc -l &
$ time src/redis-cli keys "*" | wc -l &
$ time src/redis-cli keys "*" | wc -l &

$ free -m
              total        used        free      shared  buff/cache   available
Mem:            926         299         474          23         152         549
Mem:            926         385         388          23         152         463
Mem:            926         512         261          23         152         336
Mem:            926         573         200          23         152         275
Mem:            926         711          61          23         152         136
Mem:            926         842          21          21          62          17
-> now we used 532M memory for 36s, while Redis is hung for 26s
-> but we still have a running Redis

Let's run 4 KEYS commands at the (almost) same time (that will run one after another anyway)
$ time src/redis-cli keys "*" | wc -l &
$ time src/redis-cli keys "*" | wc -l &
$ time src/redis-cli keys "*" | wc -l &
$ time src/redis-cli keys "*" | wc -l &
-> that kills Redis

Redis 日志中没有任何内容:

2251:C 19 May 16:03:05.355 * DB saved on disk
2251:C 19 May 16:03:05.379 * RDB: 2 MB of memory used by copy-on-write
1853:M 19 May 16:03:05.432 * Background saving terminated with success

在 /var/log/messages 中

May 19 16:08:01 consumer2 kernel: [454881.744017] redis-cli invoked oom-killer: gfp_mask=0x6200ca(GFP_HIGHUSER_MOVABLE), nodemask=(null), order=0, oom_score_adj=0
May 19 16:08:01 consumer2 kernel: [454881.744180] [<8023bdb8>] (oom_kill_process) from [<8023c6e8>] (out_of_memory+0x134/0x36c)

结论:

  • 我们可以杀死健康的 Redis 实例,消耗 200M RAM,其中操作系统上有 70% 的 RAM 可用,只需运行 4 个 KEYS 命令,一个接一个地发出并一个接一个地运行。只是因为即使 Redis 执行完毕,结果也必须被缓冲。
  • 无法使用 maxmemory 保护 Redis 免受这种行为的影响,因为内存使用不是 SET 命令的结果
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么Redis中不建议使用KEYS? 的相关文章

  • 将 StackExchange.Redis 客户端与 Redis 集群结合使用

    如何告诉 StackExchange Redis v1 0 481 它即将连接到 Redis 集群 v3 2 6 如果重要的话 而不仅仅是独立 复制实例 例如 当我使用 redis cli 时 我必须传递 c 标志以使其具有集群感知能力 S
  • Redis CLI 未通过 Laravel 显示最近存储的密钥

    我正在尝试使用缓存我的结果redis in Laravel通过做这个 result Cache remember orders cache 10 function use orders return orders return result
  • 连接远程redis服务器

    我想对 redis conf 进行一些更改 以便每当我输入 redis cli 时 它都会将我连接到远程服务器上安装的 redis 我知道我们可以通过以下方式连接到安装在远程服务器上的redis redis cli h IP Address
  • 在 aws 微实例上安装 redis

    我需要在亚马逊云中安装redis 我需要它作为我的 npm 模块 kue 部署 的一部分 考虑到我对 Linux 和管理的了解并不好 任何人都可以链接我的逐步教程或解释如何做到这一点 如果您启用 Amazon Linux 上存在的 Extr
  • ServiceStack:手动调用服务时恢复管道?

    作为后续这个问题 https stackoverflow com questions 64560997 servicestack messaging api can it make a broadcast 我想了解如何改进我对服务的手动调用
  • 如何在多线程应用程序中使用 StackExchange.Redis IDatabase 对象?

    我从 StackExchange Redis 文档中收到有关如何使用 IDatabase 的混合消息 在里面基本使用文档 https github com StackExchange StackExchange Redis blob mas
  • 在节点中使用redis获取hash key的所有字段和值

    红色是使用哈希 我需要存储具有多个字段和值的哈希键 我尝试如下 client hmset Table1 Id 9324324 ReqNo 23432 redis print client hmset Table1 Id 9324325 Re
  • 是否可以使用带有 FUSE 文件系统的 Linux VFS 缓存?

    默认情况下 Linux VFS 缓存似乎不适用于 FUSE 文件系统 例如 read 调用似乎被系统地转发到 FUSE 文件系统 我在 FUSE 特定的远程文件系统上工作 我需要一个非常积极的缓存 我需要实现自己的页面缓存吗 或者是否可以为
  • 连接到 localhost:6379 时出现错误 99。无法分配请求的地址

    设置 我有一个虚拟机 并在虚拟机中运行三个容器 一个 nginx 代理 一个非常简约的 Flask 应用程序和 redis Flask 应在端口 5000 上提供服务 而 redis 应在 6379 上提供服务 这些容器中的每一个都可以作为
  • Redis 写入 .ssh/authorized_keys

    当前设置 2 个主服务器 12 个工作服务器 工作人员通过 ssh copy id 连接到主设备 主设备和工作人员正在主设备上的 redis 队列中写入数据 过去一周我遇到的问题是 Redis 正在将数据写入authorized keys
  • 如何从 python 将无穷大传递给 redis?

    我正在使用 redis py 并希望将 inf 和 inf 与 ZRANGEBYSCORE 一起使用 我尝试使用 inf 的字符串和浮点来执行此操作 但它们返回一个空集 我怎样才能做到这一点 EDIT 我尝试执行以下命令 redis Str
  • 保护节点 Redis

    我正在尝试保护 Node Redis IPC 服务器以使用私钥 公钥 我已经关注了本教程 http bencane com 2014 02 18 sending redis traffic through an ssl tunnel wit
  • Redis 块推送直到列表有空位

    我正在寻找类似的东西BLPUSH该命令将阻塞 直到列表的长度低于指定值max size 目的是防止生产者运行速度快于消费者时列表无限增长 功能与 python 非常相似Queue put https docs python org 3 li
  • 使用 AWS ElastiCache 请求中的 Airflow CROSSSLOT 密钥未散列到同一插槽错误

    我在 AWS ECS 上运行 apache airflow 1 8 1 并且有一个 AWS ElastiCache 集群 redis 3 2 4 运行 2 个分片 2 个启用多可用区的节点 集群 Redis 引擎 我已经验证气流可以毫无问题
  • Redis键空间事件不触发

    我有两个 Redis 客户端 在一个文件中我有一个简单的脚本设置并删除了 Redis 键 var redis require redis var client redis createClient 6379 127 0 0 1 client
  • 为什么Redis中不建议使用KEYS?

    在Redis中 建议不要使用按键命令 https redis io commands KEYS 为什么会这样呢 是因为它的时间复杂度是 O N 吗 或者是别的什么原因 我做了下面的实验来证明KEYS命令有多么危险 当带有 KEYS 的一个命
  • 库存管理系统的 SQL 与 NoSQL

    我正在开发一个基于 JAVA 的网络应用程序 主要目的是拥有在多个称为渠道的网站上销售的产品的库存 我们将担任所有这些渠道的管理者 我们需要的是 用于管理每个渠道的库存更新的队列 库存表 其中包含每个通道上分配的正确快照 将会话 ID 和其
  • Redis hash写入速度非常慢

    我面临一个非常奇怪的问题 使用 Redis 时 我的写入速度非常糟糕 在理想的情况下 写入速度应该接近 RAM 上的写入速度 这是我的基准 package redisbenchmark import redis clients jedis
  • Spring Data Redis - Lettuce连接池设置

    尝试在 spring data redis 环境中设置 Lettuce 连接池 下面是代码 Bean LettuceConnectionFactory redisConnectionFactory GenericObjectPoolConf
  • 从redis中检索大数据集

    一台服务器上的应用程序查询另一台服务器上运行的 Redis 查询的结果数据集约为 250kzrangebyscore objects locations inf inf这在应用程序服务器上似乎需要 40 秒 当使用命令执行时redis cl

随机推荐

  • 如何使用 Netty 发送对象?

    如何通过Netty从服务器端发送bean并在客户端接收该bean 当我发送简单的整数消息 inputstream 时 它工作成功 但我需要发送 bean 如果您在客户端和服务器端使用 Netty 那么您可以使用 Netty对象解码器 htt
  • 以编程方式关闭 WP7 应用程序? [复制]

    这个问题在这里已经有答案了 可能的重复 Windows Phone 7 关闭应用程序 https stackoverflow com questions 3659195 windows phone 7 close application 如
  • 表达忽略视图目录

    我已经设置了一个配置文件来存储我的 Express 应用程序的应用程序路径 cookie 秘密等设置 问题是它似乎忽略了我的视图路径目录设置 配置 js exports server port 3000 cookie secret path
  • 使用类的 __new__ 方法作为工厂:__init__ 被调用两次

    我在 python 中遇到了一个奇怪的错误 其中使用 new 将类的方法作为工厂会导致 init 实例化类的方法被调用两次 这个想法最初是为了使用 new 母类的方法根据传递的参数返回其子类之一的特定实例 而无需在类外部声明工厂函数 我知道
  • 需要类或命名空间;语法正确且正确

    在 dualstk h 中 ifndef 32 dualstk h define 32 dualstk h include
  • AWS 检查状态机/Step Functions 并发运行

    我在处理状态机 步骤函数 的并发运行时遇到很多问题 该状态机中确实有胶水作业任务 状态机由 Lambda 启动 并由 FIFO SQS 队列触发 lambda 获取消息 检查正在运行的状态机实例数量 如果该数量低于 GlueJob 并发运行
  • .htaccess 将一个文件夹中的所有文件重定向到另一个文件夹中的完全相同的文件

    我们只需将名为 音乐 的目录中的每个页面移动到名为 信息 的目录 这是唯一的更改 有很多指向音乐页面的链接 我们不想全部破坏 我不擅长重写条件 基本上 我想做的就是当用户输入 music index php 或 music life myp
  • 复合属性

    有没有办法在 C 中制作复合属性以在编译时提供等效的元数据 例如 改变 ClassInterface ClassInterfaceType AutoDual ProgId MyProgId MyMefExport MyProgId publ
  • 有没有办法使用 getUserMedia 减少延迟?

    在尝试减少视频延迟的同时WebRTC通信时 我测量了视频捕获和视频显示之间的延迟 为了防止测量 WebRTC 涉及的延迟 我只是使用getUserMedia和一个 HTMLvideo显示流 我通过每帧显示时间戳来做到这一点 使用reques
  • 编译器错误:对调用的引用不明确

    Case 1 static void call Integer i System out println hi i static void call int i System out println hello i public stati
  • 更改 ToolStripMenuItem 的大小

    我正在自定义绘制一个菜单项MenuStrip 我遇到的问题是菜单项坚持根据文本调整自身大小 这不是我想要的 没有文本 我可以设置AutoSize设置为 false 并显式指定大小 但包含的菜单 ToolStripDropDown 仍然根据文
  • $_POST、$_GET 和 $_REQUEST 为空

    SOLVED 我省略了输入字段中的名称属性 我有一个简单的 html php 表单 我提交了 POST 始终为空 如果我尝试 get 那么 GET 总是空的 REQUEST 和 php input 相同 我没有得到任何回报 有很多关于这个主
  • AVCaptureVideoPreviewLayer 和从相机位置预览

    我正在开发一个允许用户拍照的应用程序 我已经开始使用AVCam https developer apple com library ios samplecode AVCam Introduction Intro html苹果提供了 但我实际
  • ElasticSearch - 索引模板和索引模式有什么区别

    我在这里阅读了对我的问题的解释 https discuss elastic co t whats the differece Between index pattern and index template 54948 https disc
  • 如何通过 django admin 中的操作请求用户输入?

    在我的代码中 我正在编写一个分组操作 我想询问用户每个组需要多少人 然后用一个警报框进行响应 根据用户输入显示 您有 4 个组 的内容 我如何在 django admin 中执行此操作 如何创建某种弹出窗口来询问他们想要放入一个组中的人数
  • 默认移动构造函数/赋值和删除的复制构造函数/赋值

    根据标准 如果类 X 的定义没有显式声明移动构造函数 则当且仅当 X 没有用户声明的复制构造函数 X 没有用户声明的复制赋值运算符 X 没有用户声明的移动赋值运算符 并且 X 没有用户声明的析构函数 现在以下无法编译 include
  • Highstocks 图表宽度未正确呈现

    您好 我在使用 jquery 选项卡时遇到 highstocks 问题 这是构造函数的代码 Chart new Highcharts StockChart Chart new Highcharts StockChart chart rend
  • 在调试或正常运行时读取字符串时出现 NullReferenceException [关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 当尝试在调用时读取文件时DoSomething from Something 在里面TestProgram Load 方
  • WebSocket 库 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想在 Linux 上使用 C 访问 WebSocket API 我见过不同的图书馆 比如libweb
  • 为什么Redis中不建议使用KEYS?

    在Redis中 建议不要使用按键命令 https redis io commands KEYS 为什么会这样呢 是因为它的时间复杂度是 O N 吗 或者是别的什么原因 我做了下面的实验来证明KEYS命令有多么危险 当带有 KEYS 的一个命